diff --git a/go.mod b/go.mod index ffd7ca2..2d24ffb 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module git.frostfs.info/TrueCloudLab/xk6-frostfs -go 1.19 +go 1.20 require ( - git.frostfs.info/TrueCloudLab/frostfs-node v0.22.2-0.20230704155826-b520a3049e6f + git.frostfs.info/TrueCloudLab/frostfs-node v0.37.1-0.20231213105742-e39db63827d8 git.frostfs.info/TrueCloudLab/frostfs-s3-gw v0.27.0-rc.2 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230705125206-769f6eec0565 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/aws/aws-sdk-go-v2 v1.19.0 github.com/aws/aws-sdk-go-v2/config v1.18.28 @@ -15,7 +15,7 @@ require ( github.com/go-loremipsum/loremipsum v1.1.3 github.com/google/uuid v1.3.0 github.com/joho/godotenv v1.5.1 - github.com/nspcc-dev/neo-go v0.101.2 + github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5 github.com/panjf2000/ants/v2 v2.8.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 @@ -27,7 +27,7 @@ require ( ) require ( - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230602142716-68021b910acb // indirect + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231121085847-241a9f1ad0a4 // indirect git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 // indirect git.frostfs.info/TrueCloudLab/hrw v1.2.1 // indirect @@ -55,13 +55,21 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // 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 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dlclark/regexp2 v1.10.0 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/flatbuffers v1.12.1 // indirect github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect @@ -90,6 +98,7 @@ require ( github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/gomega v1.20.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect @@ -103,6 +112,7 @@ require ( github.com/spf13/viper v1.16.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/twmb/murmur3 v1.1.8 // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.16.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 diff --git a/go.sum b/go.sum index 85d09ca..eaa7f5e 100644 --- a/go.sum +++ b/go.sum @@ -36,18 +36,18 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX 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= 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.20230602142716-68021b910acb h1:gaq4wgk7b+i9+rkDa+goPkv5FzqYlMxEuCKdZ57mSc0= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230602142716-68021b910acb/go.mod h1:pKJJRLOChW4zDQsAt1e8k/snWKljJtpkiPfxV53ngjI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231121085847-241a9f1ad0a4 h1:wjLfZ3WCt7qNGsQv+Jl0TXnmtg0uVk/jToKPFTBc/jo= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231121085847-241a9f1ad0a4/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= 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-node v0.22.2-0.20230704155826-b520a3049e6f h1:4Cs8iPGf9fJ/ozhUwwCEz9KkNEaFPRYWDm1+hz68Go4= -git.frostfs.info/TrueCloudLab/frostfs-node v0.22.2-0.20230704155826-b520a3049e6f/go.mod h1:tmU4hNqMjhyKewfX6PpzIy7y/t30diQPUxR0X/11vik= +git.frostfs.info/TrueCloudLab/frostfs-node v0.37.1-0.20231213105742-e39db63827d8 h1:GkVcsr5vo7DJFG9DiD/JNUTBCIcDqqpVvJX+4xDVNXo= +git.frostfs.info/TrueCloudLab/frostfs-node v0.37.1-0.20231213105742-e39db63827d8/go.mod h1:X7m/CJ8BgTQBQ0o4rEFNbVLSsncrJwtyqNO79r6TYe8= 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-s3-gw v0.27.0-rc.2 h1:C9Hya/NN8U7P45od221YCtL78zmIbHs9eq5AWlcNkJQ= git.frostfs.info/TrueCloudLab/frostfs-s3-gw v0.27.0-rc.2/go.mod h1:sYR/v3/WzBDAR8dLewjTxaSNYnvQtMVj0ypSy1FuLRo= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230705125206-769f6eec0565 h1:wjXxt9dpkPNQQH3bj8N/Qn7vupiB1/UWFEg1EiJUJrg= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230705125206-769f6eec0565/go.mod h1:w+s3ozlbFfTDFHhjX0A3Iif3BRtnTkwiACxFZD+Q0cQ= +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= @@ -107,6 +107,7 @@ github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0 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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -126,6 +127,12 @@ 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/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.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.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/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= @@ -135,6 +142,8 @@ github.com/dop251/goja v0.0.0-20230626124041-ba8a63e79201 h1:+9NRIliCUhliHMCixEO github.com/dop251/goja v0.0.0-20230626124041-ba8a63e79201/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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= @@ -143,7 +152,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= 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= @@ -162,11 +171,16 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible h1:bopx7t9jyUNX1ebhr0G4gtQWmUOgwQRI0QsYhdYLgkU= github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= 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.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= 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= +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= @@ -191,8 +205,12 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 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.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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/flatbuffers v1.12.1/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= @@ -201,6 +219,7 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -257,6 +276,7 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 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/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.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= @@ -302,8 +322,8 @@ github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5s 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-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= -github.com/nspcc-dev/neo-go v0.101.2 h1:E7sosxIoY0QN1IvAbkn7gjf+n8Qn2PWHTNM3kNr8Nwo= -github.com/nspcc-dev/neo-go v0.101.2/go.mod h1:J4tspxWw7jknX06F+VSMsKvIiNpYGfVTb2IxVC005YU= +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/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= @@ -387,6 +407,8 @@ 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.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= go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= @@ -488,6 +510,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 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-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -567,6 +590,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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-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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= @@ -628,6 +652,7 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY 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-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= @@ -637,6 +662,7 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f 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.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/internal/local/client.go b/internal/local/client.go index 491bce5..6116bca 100644 --- a/internal/local/client.go +++ b/internal/local/client.go @@ -13,6 +13,7 @@ import ( type Client struct { vu modules.VU rc *rawclient.RawClient + l Limiter } type ( @@ -25,6 +26,7 @@ type ( Success bool ObjectID string Error string + Abort bool } GetResponse SuccessOrErrorResponse @@ -32,6 +34,13 @@ type ( ) func (c *Client) Put(containerID string, headers map[string]string, payload goja.ArrayBuffer) PutResponse { + if c.l.IsFull() { + return PutResponse{ + Success: false, + Error: "engine size limit reached", + Abort: true, + } + } id, err := c.rc.Put(c.vu.Context(), mustParseContainerID(containerID), nil, headers, payload.Bytes()) if err != nil { return PutResponse{Error: err.Error()} diff --git a/internal/local/limiter.go b/internal/local/limiter.go new file mode 100644 index 0000000..a59f85d --- /dev/null +++ b/internal/local/limiter.go @@ -0,0 +1,89 @@ +package local + +import ( + "sync/atomic" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" +) + +var ( + _ Limiter = &noopLimiter{} + _ Limiter = &sizeLimiter{} +) + +type Limiter interface { + engine.MetricRegister + IsFull() bool +} + +func NewLimiter(maxSizeGB int64) Limiter { + if maxSizeGB < 0 { + panic("max size is negative") + } + if maxSizeGB == 0 { + return &noopLimiter{} + } + return &sizeLimiter{ + maxSize: maxSizeGB * 1024 * 1024 * 1024, + currentSize: &atomic.Int64{}, + } +} + +type sizeLimiter struct { + maxSize int64 + currentSize *atomic.Int64 +} + +func (*sizeLimiter) AddMethodDuration(method string, d time.Duration) {} +func (*sizeLimiter) AddToContainerSize(cnrID string, size int64) {} +func (*sizeLimiter) AddToObjectCounter(shardID string, objectType string, delta int) {} +func (*sizeLimiter) ClearErrorCounter(shardID string) {} +func (*sizeLimiter) DeleteShardMetrics(shardID string) {} +func (*sizeLimiter) GC() metrics.GCMetrics { return &noopGCMetrics{} } +func (*sizeLimiter) IncErrorCounter(shardID string) {} +func (*sizeLimiter) SetMode(shardID string, mode mode.Mode) {} +func (*sizeLimiter) SetObjectCounter(shardID string, objectType string, v uint64) {} +func (*sizeLimiter) WriteCache() metrics.WriteCacheMetrics { return &noopWriteCacheMetrics{} } + +func (sl *sizeLimiter) AddToPayloadCounter(shardID string, size int64) { + sl.currentSize.Add(size) +} + +func (sl *sizeLimiter) IsFull() bool { + cur := sl.currentSize.Load() + return cur > sl.maxSize +} + +type noopLimiter struct{} + +func (*noopLimiter) AddMethodDuration(method string, d time.Duration) {} +func (*noopLimiter) AddToContainerSize(cnrID string, size int64) {} +func (*noopLimiter) AddToObjectCounter(shardID string, objectType string, delta int) {} +func (*noopLimiter) AddToPayloadCounter(shardID string, size int64) {} +func (*noopLimiter) ClearErrorCounter(shardID string) {} +func (*noopLimiter) DeleteShardMetrics(shardID string) {} +func (*noopLimiter) GC() metrics.GCMetrics { return &noopGCMetrics{} } +func (*noopLimiter) IncErrorCounter(shardID string) {} +func (*noopLimiter) SetMode(shardID string, mode mode.Mode) {} +func (*noopLimiter) SetObjectCounter(shardID string, objectType string, v uint64) {} +func (*noopLimiter) WriteCache() metrics.WriteCacheMetrics { return &noopWriteCacheMetrics{} } +func (*noopLimiter) IsFull() bool { return false } + +type noopGCMetrics struct{} + +func (*noopGCMetrics) AddDeletedCount(shardID string, deleted uint64, failed uint64) {} +func (*noopGCMetrics) AddExpiredObjectCollectionDuration(string, time.Duration, bool, string) {} +func (*noopGCMetrics) AddInhumedObjectCount(shardID string, count uint64, objectType string) {} +func (*noopGCMetrics) AddRunDuration(shardID string, d time.Duration, success bool) {} + +type noopWriteCacheMetrics struct{} + +func (*noopWriteCacheMetrics) AddMethodDuration(string, string, bool, time.Duration, string) {} +func (*noopWriteCacheMetrics) Close(shardID string) {} +func (*noopWriteCacheMetrics) IncOperationCounter(string, string, metrics.NullBool, string) {} +func (*noopWriteCacheMetrics) SetActualCount(shardID string, count uint64, storageType string) {} +func (*noopWriteCacheMetrics) SetEstimateSize(shardID string, size uint64, storageType string) {} +func (*noopWriteCacheMetrics) SetMode(shardID string, mode string) {} diff --git a/internal/local/local.go b/internal/local/local.go index 22d3f6e..6e207d2 100644 --- a/internal/local/local.go +++ b/internal/local/local.go @@ -19,7 +19,8 @@ import ( metabase "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" + writecache "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" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -45,12 +46,13 @@ type RootModule struct { // ng is the engine instance used during one test, corresponding to the configFile. Each VU // gets the same engine instance. ng *engine.StorageEngine + l Limiter } // Local represents an instance of the module for every VU. type Local struct { vu modules.VU - ResolveEngine func(context.Context, string, string, bool) (*engine.StorageEngine, error) + ResolveEngine func(context.Context, string, string, bool, int64) (*engine.StorageEngine, Limiter, error) } // Ensure the interfaces are implemented correctly. @@ -73,7 +75,7 @@ func (r *RootModule) NewModuleInstance(vu modules.VU) modules.Instance { return NewLocalModuleInstance(vu, r.GetOrCreateEngine) } -func NewLocalModuleInstance(vu modules.VU, resolveEngine func(context.Context, string, string, bool) (*engine.StorageEngine, error)) *Local { +func NewLocalModuleInstance(vu modules.VU, resolveEngine func(context.Context, string, string, bool, int64) (*engine.StorageEngine, Limiter, error)) *Local { return &Local{ vu: vu, ResolveEngine: resolveEngine, @@ -105,47 +107,50 @@ func checkResourceLimits() error { // GetOrCreateEngine returns the current engine instance for the given configuration file or directory, // creating a new one if none exists. Note that the identity of configuration files is their // file name for the purposes of test runs. -func (r *RootModule) GetOrCreateEngine(ctx context.Context, configFile string, configDir string, debug bool) (*engine.StorageEngine, error) { +func (r *RootModule) GetOrCreateEngine(ctx context.Context, configFile string, configDir string, debug bool, maxSizeGB int64) (*engine.StorageEngine, Limiter, error) { r.mu.Lock() defer r.mu.Unlock() if len(configFile) == 0 && len(configDir) == 0 { - return nil, errors.New("provide configFile or configDir") + return nil, nil, errors.New("provide configFile or configDir") } + if r.l == nil { + r.l = NewLimiter(maxSizeGB) + } // Create and initialize engine for the given configFile if it doesn't exist already if r.ng == nil { r.configFile = configFile r.configDir = configDir appCfg := config.New(configFile, configDir, "") - ngOpts, shardOpts, err := storageEngineOptionsFromConfig(appCfg, debug) + ngOpts, shardOpts, err := storageEngineOptionsFromConfig(appCfg, debug, r.l) if err != nil { - return nil, fmt.Errorf("creating engine options from config: %v", err) + return nil, nil, fmt.Errorf("creating engine options from config: %v", err) } if err := checkResourceLimits(); err != nil { - return nil, err + return nil, nil, err } r.ng = engine.New(ngOpts...) for i, opts := range shardOpts { - if _, err := r.ng.AddShard(opts...); err != nil { - return nil, fmt.Errorf("adding shard %d: %v", i, err) + if _, err := r.ng.AddShard(ctx, opts...); err != nil { + return nil, nil, fmt.Errorf("adding shard %d: %v", i, err) } } - if err := r.ng.Open(); err != nil { - return nil, fmt.Errorf("opening engine: %v", err) + if err := r.ng.Open(ctx); err != nil { + return nil, nil, fmt.Errorf("opening engine: %v", err) } if err := r.ng.Init(ctx); err != nil { - return nil, fmt.Errorf("initializing engine: %v", err) + return nil, nil, fmt.Errorf("initializing engine: %v", err) } } else if configFile != r.configFile { - return nil, fmt.Errorf("GetOrCreateEngine called with mismatching configFile after engine was "+ + return nil, nil, fmt.Errorf("GetOrCreateEngine called with mismatching configFile after engine was "+ "initialized: got %q, want %q", configFile, r.configFile) } else if configDir != r.configDir { - return nil, fmt.Errorf("GetOrCreateEngine called with mismatching configDir after engine was "+ + return nil, nil, fmt.Errorf("GetOrCreateEngine called with mismatching configDir after engine was "+ "initialized: got %q, want %q", configDir, r.configDir) } - return r.ng, nil + return r.ng, r.l, nil } // Exports implements the modules.Instance interface and returns the exports @@ -156,8 +161,8 @@ func (s *Local) Exports() modules.Exports { func (s *Local) VU() modules.VU { return s.vu } -func (s *Local) Connect(configFile, configDir, hexKey string, debug bool) (*Client, error) { - ng, err := s.ResolveEngine(s.VU().Context(), configFile, configDir, debug) +func (s *Local) Connect(configFile, configDir, hexKey string, debug bool, maxSizeGB int64) (*Client, error) { + ng, l, err := s.ResolveEngine(s.VU().Context(), configFile, configDir, debug, maxSizeGB) if err != nil { return nil, fmt.Errorf("connecting to engine for config - file %q dir %q: %v", configFile, configDir, err) } @@ -211,7 +216,7 @@ func (s *Local) Connect(configFile, configDir, hexKey string, debug bool) (*Clie } }), ) - return &Client{vu: s.vu, rc: rc}, nil + return &Client{vu: s.vu, rc: rc, l: l}, nil } type epochState struct{} @@ -224,7 +229,7 @@ func (epochState) CurrentEpoch() uint64 { return 0 } // preloaded the storage (if any), by using the same configuration file. // // Note that the configuration file only needs to contain the storage-specific sections. -func storageEngineOptionsFromConfig(c *config.Config, debug bool) ([]engine.Option, [][]shard.Option, error) { +func storageEngineOptionsFromConfig(c *config.Config, debug bool, l Limiter) ([]engine.Option, [][]shard.Option, error) { log := zap.L() if debug { var err error @@ -238,6 +243,7 @@ func storageEngineOptionsFromConfig(c *config.Config, debug bool) ([]engine.Opti engine.WithErrorThreshold(engineconfig.ShardErrorThreshold(c)), engine.WithShardPoolSize(engineconfig.ShardPoolSize(c)), engine.WithLogger(&logger.Logger{Logger: log}), + engine.WithMetrics(l), } var shOpts [][]shard.Option @@ -302,15 +308,20 @@ func storageEngineOptionsFromConfig(c *config.Config, debug bool) ([]engine.Opti opts = append(opts, shard.WithWriteCache(true), shard.WithWriteCacheOptions( - writecache.WithPath(wc.Path()), - writecache.WithMaxBatchSize(wc.BoltDB().MaxBatchSize()), - writecache.WithMaxBatchDelay(wc.BoltDB().MaxBatchDelay()), - writecache.WithMaxObjectSize(wc.MaxObjectSize()), - writecache.WithSmallObjectSize(wc.SmallObjectSize()), - writecache.WithFlushWorkersCount(wc.WorkersNumber()), - writecache.WithMaxCacheSize(wc.SizeLimit()), - writecache.WithNoSync(wc.NoSync()), - writecache.WithLogger(&logger.Logger{Logger: log}), + writecache.Options{ + Type: writecache.TypeBBolt, + BBoltOptions: []writecachebbolt.Option{ + writecachebbolt.WithPath(wc.Path()), + writecachebbolt.WithMaxBatchSize(wc.BoltDB().MaxBatchSize()), + writecachebbolt.WithMaxBatchDelay(wc.BoltDB().MaxBatchDelay()), + writecachebbolt.WithMaxObjectSize(wc.MaxObjectSize()), + writecachebbolt.WithSmallObjectSize(wc.SmallObjectSize()), + writecachebbolt.WithFlushWorkersCount(wc.WorkersNumber()), + writecachebbolt.WithMaxCacheSize(wc.SizeLimit()), + writecachebbolt.WithNoSync(wc.NoSync()), + writecachebbolt.WithLogger(&logger.Logger{Logger: log}), + }, + }, ), ) } diff --git a/internal/native/client.go b/internal/native/client.go index 612c59c..e4ca8e3 100644 --- a/internal/native/client.go +++ b/internal/native/client.go @@ -128,9 +128,9 @@ func (c *Client) Delete(containerID string, objectID string) DeleteResponse { start := time.Now() var prm client.PrmObjectDelete - prm.ByID(cliObjectID) - prm.FromContainer(cliContainerID) - prm.WithinSession(tok) + prm.ObjectID = &cliObjectID + prm.ContainerID = &cliContainerID + prm.Session = &tok _, err = c.cli.ObjectDelete(c.vu.Context(), prm) if err != nil { @@ -159,11 +159,11 @@ func (c *Client) Get(containerID, objectID string) GetResponse { start := time.Now() var prm client.PrmObjectGet - prm.ByID(cliObjectID) - prm.FromContainer(cliContainerID) - prm.WithinSession(tok) + prm.ObjectID = &cliObjectID + prm.ContainerID = &cliContainerID + prm.Session = &tok - var objSize = 0 + objSize := 0 err = get(c.cli, prm, c.vu.Context(), func(data []byte) { objSize += len(data) }) @@ -184,7 +184,7 @@ func get( ctx context.Context, onDataChunk func(chunk []byte), ) error { - var buf = make([]byte, defaultBufferSize) + buf := make([]byte, defaultBufferSize) objectReader, err := cli.ObjectGetInit(ctx, prm) if err != nil { @@ -227,9 +227,9 @@ func (c *Client) VerifyHash(containerID, objectID, expectedHash string) VerifyHa } var prm client.PrmObjectGet - prm.ByID(cliObjectID) - prm.FromContainer(cliContainerID) - prm.WithinSession(tok) + prm.ObjectID = &cliObjectID + prm.ContainerID = &cliContainerID + prm.Session = &tok hasher := sha256.New() err = get(c.cli, prm, c.vu.Context(), func(data []byte) { @@ -414,7 +414,8 @@ func (s epochSource) CurrentEpoch() uint64 { } func put(vu modules.VU, cli *client.Client, prepareLocally bool, tok *session.Object, - hdr *object.Object, payload []byte, chunkSize int) (*client.ResObjectPut, error) { + hdr *object.Object, payload []byte, chunkSize int, +) (*client.ResObjectPut, error) { bufSize := defaultBufferSize if chunkSize > 0 { bufSize = chunkSize diff --git a/internal/s3local/client.go b/internal/s3local/client.go index c637d2c..93c65d5 100644 --- a/internal/s3local/client.go +++ b/internal/s3local/client.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/xk6-frostfs/internal/local" "git.frostfs.info/TrueCloudLab/xk6-frostfs/internal/stats" "github.com/dop251/goja" "go.k6.io/k6/js/modules" @@ -18,11 +19,13 @@ type Client struct { l layer.Client ownerID *user.ID resolver layer.BucketResolver + limiter local.Limiter } type ( SuccessOrErrorResponse struct { Success bool + Abort bool Error string } @@ -33,6 +36,13 @@ type ( ) func (c *Client) Put(bucket, key string, payload goja.ArrayBuffer) PutResponse { + if c.limiter.IsFull() { + return PutResponse{ + Success: false, + Abort: true, + Error: "engine size limit reached", + } + } cid, err := c.resolver.Resolve(c.vu.Context(), bucket) if err != nil { stats.Report(c.vu, objPutFails, 1) diff --git a/internal/s3local/local.go b/internal/s3local/local.go index 531ac15..e760fe7 100644 --- a/internal/s3local/local.go +++ b/internal/s3local/local.go @@ -56,7 +56,7 @@ func (s *Local) Exports() modules.Exports { return modules.Exports{Default: s} } -func (s *Local) Connect(configFile string, configDir string, params map[string]string, bucketMapping map[string]string) (*Client, error) { +func (s *Local) Connect(configFile string, configDir string, params map[string]string, bucketMapping map[string]string, maxSizeGB int64) (*Client, error) { // Parse configuration flags. fs := flag.NewFlagSet("s3local", flag.ContinueOnError) @@ -107,7 +107,7 @@ func (s *Local) Connect(configFile string, configDir string, params map[string]s objGetDuration, _ = registry.NewMetric("s3local_obj_get_duration", metrics.Trend, metrics.Time) // Create S3 layer backed by local storage engine and tree service. - ng, err := s.l.ResolveEngine(s.l.VU().Context(), configFile, configDir, *debugLogger) + ng, limiter, err := s.l.ResolveEngine(s.l.VU().Context(), configFile, configDir, *debugLogger, maxSizeGB) if err != nil { return nil, fmt.Errorf("connecting to engine for config - file %q dir %q: %v", configFile, configDir, err) } @@ -158,6 +158,7 @@ func (s *Local) Connect(configFile string, configDir string, params map[string]s l: l, ownerID: rc.OwnerID(), resolver: resolver, + limiter: limiter, }, nil } diff --git a/internal/s3local/treeService.go b/internal/s3local/treeService.go index c319e4a..ff507b7 100644 --- a/internal/s3local/treeService.go +++ b/internal/s3local/treeService.go @@ -115,7 +115,7 @@ func (s treeServiceEngineWrapper) GetSubTree(ctx context.Context, bktInfo *data. return fmt.Errorf("getting children: %v", err) } for _, child := range children { - if err := traverse(child, curDepth+1); err != nil { + if err := traverse(child.ID, curDepth+1); err != nil { return err } } diff --git a/scenarios/local.js b/scenarios/local.js index d706ee3..648bead 100644 --- a/scenarios/local.js +++ b/scenarios/local.js @@ -6,6 +6,7 @@ import { SharedArray } from 'k6/data'; import { textSummary } from './libs/k6-summary-0.0.2.js'; import { parseEnv } from './libs/env-parser.js'; import { uuidv4 } from './libs/k6-utils-1.4.0.js'; +import exec from 'k6/execution'; parseEnv(); @@ -23,7 +24,8 @@ const summary_json = __ENV.SUMMARY_JSON || "/tmp/summary.json"; const config_file = __ENV.CONFIG_FILE; const config_dir = __ENV.CONFIG_DIR; const debug_logger = (__ENV.DEBUG_LOGGER || 'false') == 'true'; -const local_client = local.connect(config_file, config_dir, '', debug_logger); +const max_total_size_gb = __ENV.MAX_TOTAL_SIZE_GB ? parseInt(__ENV.MAX_TOTAL_SIZE_GB) : 0; +const local_client = local.connect(config_file, config_dir, '', debug_logger, max_total_size_gb); const log = logging.new().withFields({"config_file": config_file,"config_dir": config_dir}); const registry_enabled = !!__ENV.REGISTRY_FILE; @@ -130,6 +132,9 @@ export function obj_write() { const { payload, hash } = generator.genPayload(registry_enabled); const resp = local_client.put(container, headers, payload); if (!resp.success) { + if (resp.abort) { + exec.test.abort(resp.error); + } log.withField("cid", container).error(resp.error); return; } diff --git a/scenarios/run_scenarios.md b/scenarios/run_scenarios.md index 15999ea..846e075 100644 --- a/scenarios/run_scenarios.md +++ b/scenarios/run_scenarios.md @@ -76,6 +76,7 @@ Options (in addition to the common options): * `CONFIG_FILE` - path to the local configuration file used for the storage node. Only the storage configuration section is used. * `DELETERS` - number of VUs performing delete operations (using deleters requires that options `DELETE_AGE` and `REGISTRY_FILE` are specified as well). * `DELETE_AGE` - age of object in seconds before which it can not be deleted. This parameter can be used to control how many objects we have in the system under load. + * `MAX_TOTAL_SIZE_GB` - if specified, max payload size in GB of the storage engine. If the storage engine is already full, no new objects will be saved. ## HTTP @@ -182,6 +183,7 @@ Note that the `s3local` scenario currently does not support deleters. Options (in addition to the common options): * `OBJ_NAME` - if specified, this name will be used for all write operations instead of random generation. + * `MAX_TOTAL_SIZE_GB` - if specified, max payload size in GB of the storage engine. If the storage engine is already full, no new objects will be saved. ## Verify diff --git a/scenarios/s3local.js b/scenarios/s3local.js index d058b33..b04a6a3 100644 --- a/scenarios/s3local.js +++ b/scenarios/s3local.js @@ -6,6 +6,7 @@ import { SharedArray } from 'k6/data'; import { textSummary } from './libs/k6-summary-0.0.2.js'; import { parseEnv } from './libs/env-parser.js'; import { uuidv4 } from './libs/k6-utils-1.4.0.js'; +import exec from 'k6/execution'; parseEnv(); @@ -37,9 +38,10 @@ const summary_json = __ENV.SUMMARY_JSON || "/tmp/summary.json"; const config_file = __ENV.CONFIG_FILE; const config_dir = __ENV.CONFIG_DIR; +const max_total_size_gb = __ENV.MAX_TOTAL_SIZE_GB ? parseInt(__ENV.MAX_TOTAL_SIZE_GB) : 0; const s3_client = s3local.connect(config_file, config_dir, { 'debug_logger': __ENV.DEBUG_LOGGER || 'false', -}, bucket_mapping()); +}, bucket_mapping(), max_total_size_gb); const log = logging.new().withFields({"config_file": config_file,"config_dir": config_dir}); const registry_enabled = !!__ENV.REGISTRY_FILE; @@ -126,6 +128,9 @@ export function obj_write() { const { payload, hash } = generator.genPayload(registry_enabled); const resp = s3_client.put(bucket, key, payload); if (!resp.success) { + if (resp.abort) { + exec.test.abort(resp.error); + } log.withFields({bucket: bucket, key: key}).error(resp.error); return; }