frostfs-node/pkg/services/object/patch/range_provider.go
Airat Arifullin 6488ddee88
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 1m50s
DCO action / DCO (pull_request) Successful in 1m54s
Vulncheck / Vulncheck (pull_request) Successful in 2m29s
Tests and linters / Tests (1.23) (pull_request) Successful in 2m58s
Tests and linters / Tests (1.22) (pull_request) Successful in 2m59s
Tests and linters / Lint (pull_request) Successful in 3m17s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m3s
Build / Build Components (1.23) (pull_request) Successful in 3m12s
Build / Build Components (1.22) (pull_request) Successful in 3m15s
Tests and linters / Staticcheck (pull_request) Successful in 3m35s
Tests and linters / gopls check (pull_request) Successful in 3m52s
Tests and linters / Tests with -race (pull_request) Successful in 4m11s
[#1338] object: Fix range provider in Patch handler
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-08-27 16:51:12 +03:00

75 lines
1.7 KiB
Go

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 {
// 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
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
}
type nopReader struct{}
func (nopReader) Read(_ []byte) (int, error) {
return 0, io.EOF
}