[#131] client: Re-implement Object Delete and Hash methods
Also remove unused methods of `pool.Client` and `pool.Pool`. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
fb3501752d
commit
28b49419ab
4 changed files with 347 additions and 228 deletions
134
client/object_delete.go
Normal file
134
client/object_delete.go
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
|
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PrmObjectDelete groups parameters of ObjectDelete operation.
|
||||||
|
type PrmObjectDelete struct {
|
||||||
|
meta v2session.RequestMetaHeader
|
||||||
|
|
||||||
|
body v2object.DeleteRequestBody
|
||||||
|
|
||||||
|
addr v2refs.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithinSession specifies session within which object should be read.
|
||||||
|
//
|
||||||
|
// Creator of the session acquires the authorship of the request.
|
||||||
|
// This may affect the execution of an operation (e.g. access control).
|
||||||
|
//
|
||||||
|
// Must be signed.
|
||||||
|
func (x *PrmObjectDelete) WithinSession(t session.Token) {
|
||||||
|
x.meta.SetSessionToken(t.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBearerToken attaches bearer token to be used for the operation.
|
||||||
|
//
|
||||||
|
// If set, underlying eACL rules will be used in access control.
|
||||||
|
//
|
||||||
|
// Must be signed.
|
||||||
|
func (x *PrmObjectDelete) WithBearerToken(t token.BearerToken) {
|
||||||
|
x.meta.SetBearerToken(t.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContainer specifies NeoFS container of the object.
|
||||||
|
// Required parameter.
|
||||||
|
func (x *PrmObjectDelete) FromContainer(id cid.ID) {
|
||||||
|
x.addr.SetContainerID(id.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByID specifies identifier of the requested object.
|
||||||
|
// Required parameter.
|
||||||
|
func (x *PrmObjectDelete) ByID(id oid.ID) {
|
||||||
|
x.addr.SetObjectID(id.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResObjectDelete groups resulting values of ObjectDelete operation.
|
||||||
|
type ResObjectDelete struct {
|
||||||
|
statusRes
|
||||||
|
|
||||||
|
idTomb *v2refs.ObjectID
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadTombstoneID reads identifier of the created tombstone object.
|
||||||
|
// Returns false if ID is missing (not read).
|
||||||
|
func (x ResObjectDelete) ReadTombstoneID(dst *oid.ID) bool {
|
||||||
|
if x.idTomb != nil {
|
||||||
|
*dst = *oid.NewIDFromV2(x.idTomb) // need smth better
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectDelete marks an object for deletion from the container using NeoFS API protocol.
|
||||||
|
// As a marker, a special unit called a tombstone is placed in the container.
|
||||||
|
// It confirms the user's intent to delete the object, and is itself a container object.
|
||||||
|
// Explicit deletion is done asynchronously, and is generally not guaranteed.
|
||||||
|
//
|
||||||
|
// Returns a list of checksums in raw form: the format of hashes and their number
|
||||||
|
// is left for the caller to check. Client preserves the order of the server's response.
|
||||||
|
//
|
||||||
|
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
||||||
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
|
// If WithNeoFSErrorParsing option has been provided, unsuccessful
|
||||||
|
// NeoFS status codes are returned as `error`, otherwise, are included
|
||||||
|
// in the returned result structure.
|
||||||
|
//
|
||||||
|
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
|
||||||
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
|
//
|
||||||
|
// Return statuses:
|
||||||
|
// - global (see Client docs).
|
||||||
|
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
|
||||||
|
switch {
|
||||||
|
case ctx == nil:
|
||||||
|
panic(panicMsgMissingContext)
|
||||||
|
case prm.addr.GetContainerID() == nil:
|
||||||
|
panic(panicMsgMissingContainer)
|
||||||
|
case prm.addr.GetObjectID() == nil:
|
||||||
|
panic("missing object")
|
||||||
|
}
|
||||||
|
|
||||||
|
// form request body
|
||||||
|
prm.body.SetAddress(&prm.addr)
|
||||||
|
|
||||||
|
// form request
|
||||||
|
var req v2object.DeleteRequest
|
||||||
|
req.SetBody(&prm.body)
|
||||||
|
req.SetMetaHeader(&prm.meta)
|
||||||
|
|
||||||
|
// init call context
|
||||||
|
var (
|
||||||
|
cc contextCall
|
||||||
|
res ResObjectDelete
|
||||||
|
)
|
||||||
|
|
||||||
|
c.initCallContext(&cc)
|
||||||
|
cc.req = &req
|
||||||
|
cc.statusRes = &res
|
||||||
|
cc.call = func() (responseV2, error) {
|
||||||
|
return rpcapi.DeleteObject(c.Raw(), &req, client.WithContext(ctx))
|
||||||
|
}
|
||||||
|
cc.result = func(r responseV2) {
|
||||||
|
res.idTomb = r.(*v2object.DeleteResponse).GetBody().GetTombstone().GetObjectID()
|
||||||
|
}
|
||||||
|
|
||||||
|
// process call
|
||||||
|
if !cc.processCall() {
|
||||||
|
return nil, cc.err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
178
client/object_hash.go
Normal file
178
client/object_hash.go
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
|
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PrmObjectHash groups parameters of ObjectHash operation.
|
||||||
|
type PrmObjectHash struct {
|
||||||
|
meta v2session.RequestMetaHeader
|
||||||
|
|
||||||
|
body v2object.GetRangeHashRequestBody
|
||||||
|
|
||||||
|
tillichZemor bool
|
||||||
|
|
||||||
|
addr v2refs.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkLocal tells the server to execute the operation locally.
|
||||||
|
func (x *PrmObjectHash) MarkLocal() {
|
||||||
|
x.meta.SetTTL(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithinSession specifies session within which object should be read.
|
||||||
|
//
|
||||||
|
// Creator of the session acquires the authorship of the request.
|
||||||
|
// This may affect the execution of an operation (e.g. access control).
|
||||||
|
//
|
||||||
|
// Must be signed.
|
||||||
|
func (x *PrmObjectHash) WithinSession(t session.Token) {
|
||||||
|
x.meta.SetSessionToken(t.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBearerToken attaches bearer token to be used for the operation.
|
||||||
|
//
|
||||||
|
// If set, underlying eACL rules will be used in access control.
|
||||||
|
//
|
||||||
|
// Must be signed.
|
||||||
|
func (x *PrmObjectHash) WithBearerToken(t token.BearerToken) {
|
||||||
|
x.meta.SetBearerToken(t.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContainer specifies NeoFS container of the object.
|
||||||
|
// Required parameter.
|
||||||
|
func (x *PrmObjectHash) FromContainer(id cid.ID) {
|
||||||
|
x.addr.SetContainerID(id.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByID specifies identifier of the requested object.
|
||||||
|
// Required parameter.
|
||||||
|
func (x *PrmObjectHash) ByID(id oid.ID) {
|
||||||
|
x.addr.SetObjectID(id.ToV2())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRangeList sets list of ranges in (offset, length) pair format.
|
||||||
|
// Required parameter.
|
||||||
|
//
|
||||||
|
// If passed as slice, then it must not be mutated before the operation completes.
|
||||||
|
func (x *PrmObjectHash) SetRangeList(r ...uint64) {
|
||||||
|
ln := len(r)
|
||||||
|
if ln%2 != 0 {
|
||||||
|
panic("odd number of range parameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
rs := make([]*v2object.Range, ln/2)
|
||||||
|
|
||||||
|
for i := 0; i < ln/2; i++ {
|
||||||
|
rs[i] = new(v2object.Range)
|
||||||
|
rs[i].SetOffset(r[2*i])
|
||||||
|
rs[i].SetOffset(r[2*i+1])
|
||||||
|
}
|
||||||
|
|
||||||
|
x.body.SetRanges(rs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TillichZemorAlgo changes the hash function to Tillich-Zemor
|
||||||
|
// (https://link.springer.com/content/pdf/10.1007/3-540-48658-5_5.pdf).
|
||||||
|
//
|
||||||
|
// By default, SHA256 hash function is used.
|
||||||
|
func (x *PrmObjectHash) TillichZemorAlgo() {
|
||||||
|
x.tillichZemor = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseSalt sets the salt to XOR the data range before hashing.
|
||||||
|
//
|
||||||
|
// Must not be mutated before the operation completes.
|
||||||
|
func (x *PrmObjectHash) UseSalt(salt []byte) {
|
||||||
|
x.body.SetSalt(salt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResObjectHash groups resulting values of ObjectHash operation.
|
||||||
|
type ResObjectHash struct {
|
||||||
|
statusRes
|
||||||
|
|
||||||
|
checksums [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checksums returns a list of calculated checksums in range order.
|
||||||
|
func (x ResObjectHash) Checksums() [][]byte {
|
||||||
|
return x.checksums
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectHash requests checksum of the range list of the object payload using
|
||||||
|
// NeoFS API protocol.
|
||||||
|
//
|
||||||
|
// Returns a list of checksums in raw form: the format of hashes and their number
|
||||||
|
// is left for the caller to check. Client preserves the order of the server's response.
|
||||||
|
//
|
||||||
|
// Exactly one return value is non-nil. By default, server status is returned in res structure.
|
||||||
|
// Any client's internal or transport errors are returned as `error`,
|
||||||
|
// If WithNeoFSErrorParsing option has been provided, unsuccessful
|
||||||
|
// NeoFS status codes are returned as `error`, otherwise, are included
|
||||||
|
// in the returned result structure.
|
||||||
|
//
|
||||||
|
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
|
||||||
|
// Context is required and must not be nil. It is used for network communication.
|
||||||
|
//
|
||||||
|
// Return statuses:
|
||||||
|
// - global (see Client docs).
|
||||||
|
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
|
||||||
|
switch {
|
||||||
|
case ctx == nil:
|
||||||
|
panic(panicMsgMissingContext)
|
||||||
|
case prm.addr.GetContainerID() == nil:
|
||||||
|
panic(panicMsgMissingContainer)
|
||||||
|
case prm.addr.GetObjectID() == nil:
|
||||||
|
panic("missing object")
|
||||||
|
case len(prm.body.GetRanges()) == 0:
|
||||||
|
panic("missing ranges")
|
||||||
|
}
|
||||||
|
|
||||||
|
// form request body
|
||||||
|
prm.body.SetAddress(&prm.addr)
|
||||||
|
// ranges and salt are already by prm setters
|
||||||
|
|
||||||
|
if prm.tillichZemor {
|
||||||
|
prm.body.SetType(v2refs.TillichZemor)
|
||||||
|
} else {
|
||||||
|
prm.body.SetType(v2refs.SHA256)
|
||||||
|
}
|
||||||
|
|
||||||
|
// form request
|
||||||
|
var req v2object.GetRangeHashRequest
|
||||||
|
req.SetBody(&prm.body)
|
||||||
|
req.SetMetaHeader(&prm.meta)
|
||||||
|
|
||||||
|
// init call context
|
||||||
|
var (
|
||||||
|
cc contextCall
|
||||||
|
res ResObjectHash
|
||||||
|
)
|
||||||
|
|
||||||
|
c.initCallContext(&cc)
|
||||||
|
cc.req = &req
|
||||||
|
cc.statusRes = &res
|
||||||
|
cc.call = func() (responseV2, error) {
|
||||||
|
return rpcapi.HashObjectRange(c.Raw(), &req, client.WithContext(ctx))
|
||||||
|
}
|
||||||
|
cc.result = func(r responseV2) {
|
||||||
|
res.checksums = r.(*v2object.GetRangeHashResponse).GetBody().GetHashList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// process call
|
||||||
|
if !cc.processCall() {
|
||||||
|
return nil, cc.err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
|
@ -6,11 +6,9 @@ package pool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
io "io"
|
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
client "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
|
||||||
client0 "github.com/nspcc-dev/neofs-sdk-go/client"
|
client0 "github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,71 +35,6 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnnounceContainerUsedSpace mocks base method.
|
|
||||||
func (m *MockClient) AnnounceContainerUsedSpace(arg0 context.Context, arg1 client0.AnnounceSpacePrm) (*client0.AnnounceSpaceRes, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
ret := m.ctrl.Call(m, "AnnounceContainerUsedSpace", varargs...)
|
|
||||||
ret0, _ := ret[0].(*client0.AnnounceSpaceRes)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceContainerUsedSpace indicates an expected call of AnnounceContainerUsedSpace.
|
|
||||||
func (mr *MockClientMockRecorder) AnnounceContainerUsedSpace(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AnnounceContainerUsedSpace", reflect.TypeOf((*MockClient)(nil).AnnounceContainerUsedSpace), varargs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceIntermediateTrust mocks base method.
|
|
||||||
func (m *MockClient) AnnounceIntermediateTrust(arg0 context.Context, arg1 client0.AnnounceIntermediateTrustPrm) (*client0.AnnounceIntermediateTrustRes, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
ret := m.ctrl.Call(m, "AnnounceIntermediateTrust", varargs...)
|
|
||||||
ret0, _ := ret[0].(*client0.AnnounceIntermediateTrustRes)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceIntermediateTrust indicates an expected call of AnnounceIntermediateTrust.
|
|
||||||
func (mr *MockClientMockRecorder) AnnounceIntermediateTrust(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AnnounceIntermediateTrust", reflect.TypeOf((*MockClient)(nil).AnnounceIntermediateTrust), varargs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceLocalTrust mocks base method.
|
|
||||||
func (m *MockClient) AnnounceLocalTrust(arg0 context.Context, arg1 client0.AnnounceLocalTrustPrm) (*client0.AnnounceLocalTrustRes, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
ret := m.ctrl.Call(m, "AnnounceLocalTrust", varargs...)
|
|
||||||
ret0, _ := ret[0].(*client0.AnnounceLocalTrustRes)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceLocalTrust indicates an expected call of AnnounceLocalTrust.
|
|
||||||
func (mr *MockClientMockRecorder) AnnounceLocalTrust(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AnnounceLocalTrust", reflect.TypeOf((*MockClient)(nil).AnnounceLocalTrust), varargs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conn mocks base method.
|
|
||||||
func (m *MockClient) Conn() io.Closer {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "Conn")
|
|
||||||
ret0, _ := ret[0].(io.Closer)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conn indicates an expected call of Conn.
|
|
||||||
func (mr *MockClientMockRecorder) Conn() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Conn", reflect.TypeOf((*MockClient)(nil).Conn))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSession mocks base method.
|
// CreateSession mocks base method.
|
||||||
func (m *MockClient) CreateSession(arg0 context.Context, arg1 client0.CreateSessionPrm) (*client0.CreateSessionRes, error) {
|
func (m *MockClient) CreateSession(arg0 context.Context, arg1 client0.CreateSessionPrm) (*client0.CreateSessionRes, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -136,15 +69,11 @@ func (mr *MockClientMockRecorder) DeleteContainer(arg0, arg1 interface{}) *gomoc
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteContainer", reflect.TypeOf((*MockClient)(nil).DeleteContainer), varargs...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteContainer", reflect.TypeOf((*MockClient)(nil).DeleteContainer), varargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObject mocks base method.
|
// ObjectDelete mocks base method.
|
||||||
func (m *MockClient) DeleteObject(arg0 context.Context, arg1 *client0.DeleteObjectParams, arg2 ...client0.CallOption) (*client0.ObjectDeleteRes, error) {
|
func (m *MockClient) ObjectDelete(arg0 context.Context, arg1 client0.PrmObjectDelete) (*client0.ResObjectDelete, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
varargs := []interface{}{arg0, arg1}
|
ret := m.ctrl.Call(m, "ObjectDelete", arg0, arg1)
|
||||||
for _, a := range arg2 {
|
ret0, _ := ret[0].(*client0.ResObjectDelete)
|
||||||
varargs = append(varargs, a)
|
|
||||||
}
|
|
||||||
ret := m.ctrl.Call(m, "DeleteObject", varargs...)
|
|
||||||
ret0, _ := ret[0].(*client0.ObjectDeleteRes)
|
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
@ -153,7 +82,7 @@ func (m *MockClient) DeleteObject(arg0 context.Context, arg1 *client0.DeleteObje
|
||||||
func (mr *MockClientMockRecorder) DeleteObject(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
func (mr *MockClientMockRecorder) DeleteObject(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteObject", reflect.TypeOf((*MockClient)(nil).DeleteObject), varargs...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteObject", reflect.TypeOf((*MockClient)(nil).ObjectDelete), varargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EACL mocks base method.
|
// EACL mocks base method.
|
||||||
|
@ -240,26 +169,6 @@ func (mr *MockClientMockRecorder) GetObject(arg0, arg1 interface{}, arg2 ...inte
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectGetInit", reflect.TypeOf((*MockClient)(nil).ObjectGetInit), varargs...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectGetInit", reflect.TypeOf((*MockClient)(nil).ObjectGetInit), varargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashObjectPayloadRanges mocks base method.
|
|
||||||
func (m *MockClient) HashObjectPayloadRanges(arg0 context.Context, arg1 *client0.RangeChecksumParams, arg2 ...client0.CallOption) (*client0.ObjectRangeHashRes, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
for _, a := range arg2 {
|
|
||||||
varargs = append(varargs, a)
|
|
||||||
}
|
|
||||||
ret := m.ctrl.Call(m, "HashObjectPayloadRanges", varargs...)
|
|
||||||
ret0, _ := ret[0].(*client0.ObjectRangeHashRes)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// HashObjectPayloadRanges indicates an expected call of HashObjectPayloadRanges.
|
|
||||||
func (mr *MockClientMockRecorder) HashObjectPayloadRanges(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HashObjectPayloadRanges", reflect.TypeOf((*MockClient)(nil).HashObjectPayloadRanges), varargs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectHead mocks base method.
|
// ObjectHead mocks base method.
|
||||||
func (m *MockClient) ObjectHead(arg0 context.Context, arg1 client0.PrmObjectHead) (*client0.ResObjectHead, error) {
|
func (m *MockClient) ObjectHead(arg0 context.Context, arg1 client0.PrmObjectHead) (*client0.ResObjectHead, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -359,29 +268,11 @@ func (mr *MockClientMockRecorder) PutObject(arg0, arg1 interface{}) *gomock.Call
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectPutInit", reflect.TypeOf((*MockClient)(nil).ObjectPutInit), varargs...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectPutInit", reflect.TypeOf((*MockClient)(nil).ObjectPutInit), varargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw mocks base method.
|
// ObjectSearchInitmocks base method.
|
||||||
func (m *MockClient) Raw() *client.Client {
|
func (m *MockClient) ObjectSearchInit(arg0 context.Context, arg1 client0.PrmObjectSearch) (*client0.ObjectListReader, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Raw")
|
ret := m.ctrl.Call(m, "ObjectSearchInit", arg0, arg1)
|
||||||
ret0, _ := ret[0].(*client.Client)
|
ret0, _ := ret[0].(*client0.ObjectListReader)
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Raw indicates an expected call of Raw.
|
|
||||||
func (mr *MockClientMockRecorder) Raw() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Raw", reflect.TypeOf((*MockClient)(nil).Raw))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchObjects mocks base method.
|
|
||||||
func (m *MockClient) SearchObjects(arg0 context.Context, arg1 *client0.SearchObjectParams, arg2 ...client0.CallOption) (*client0.ObjectSearchRes, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
varargs := []interface{}{arg0, arg1}
|
|
||||||
for _, a := range arg2 {
|
|
||||||
varargs = append(varargs, a)
|
|
||||||
}
|
|
||||||
ret := m.ctrl.Call(m, "SearchObjects", varargs...)
|
|
||||||
ret0, _ := ret[0].(*client0.ObjectSearchRes)
|
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
@ -390,7 +281,7 @@ func (m *MockClient) SearchObjects(arg0 context.Context, arg1 *client0.SearchObj
|
||||||
func (mr *MockClientMockRecorder) SearchObjects(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
func (mr *MockClientMockRecorder) SearchObjects(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchObjects", reflect.TypeOf((*MockClient)(nil).SearchObjects), varargs...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchObjects", reflect.TypeOf((*MockClient)(nil).ObjectSearchInit), varargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEACL mocks base method.
|
// SetEACL mocks base method.
|
||||||
|
|
134
pool/pool.go
134
pool/pool.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/sha256"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -16,7 +15,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
apiclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||||
|
@ -40,23 +38,15 @@ type Client interface {
|
||||||
DeleteContainer(context.Context, client.ContainerDeletePrm) (*client.ContainerDeleteRes, error)
|
DeleteContainer(context.Context, client.ContainerDeletePrm) (*client.ContainerDeleteRes, error)
|
||||||
EACL(context.Context, client.EACLPrm) (*client.EACLRes, error)
|
EACL(context.Context, client.EACLPrm) (*client.EACLRes, error)
|
||||||
SetEACL(context.Context, client.SetEACLPrm) (*client.SetEACLRes, error)
|
SetEACL(context.Context, client.SetEACLPrm) (*client.SetEACLRes, error)
|
||||||
AnnounceContainerUsedSpace(context.Context, client.AnnounceSpacePrm) (*client.AnnounceSpaceRes, error)
|
|
||||||
EndpointInfo(context.Context, client.EndpointInfoPrm) (*client.EndpointInfoRes, error)
|
EndpointInfo(context.Context, client.EndpointInfoPrm) (*client.EndpointInfoRes, error)
|
||||||
NetworkInfo(context.Context, client.NetworkInfoPrm) (*client.NetworkInfoRes, error)
|
NetworkInfo(context.Context, client.NetworkInfoPrm) (*client.NetworkInfoRes, error)
|
||||||
ObjectPutInit(context.Context, client.PrmObjectPutInit) (*client.ObjectWriter, error)
|
ObjectPutInit(context.Context, client.PrmObjectPutInit) (*client.ObjectWriter, error)
|
||||||
DeleteObject(context.Context, *client.DeleteObjectParams, ...client.CallOption) (*client.ObjectDeleteRes, error)
|
ObjectDelete(context.Context, client.PrmObjectDelete) (*client.ResObjectDelete, error)
|
||||||
ObjectGetInit(context.Context, client.PrmObjectGet) (*client.ObjectReader, error)
|
ObjectGetInit(context.Context, client.PrmObjectGet) (*client.ObjectReader, error)
|
||||||
ObjectHead(context.Context, client.PrmObjectHead) (*client.ResObjectHead, error)
|
ObjectHead(context.Context, client.PrmObjectHead) (*client.ResObjectHead, error)
|
||||||
ObjectRangeInit(context.Context, client.PrmObjectRange) (*client.ObjectRangeReader, error)
|
ObjectRangeInit(context.Context, client.PrmObjectRange) (*client.ObjectRangeReader, error)
|
||||||
HashObjectPayloadRanges(context.Context, *client.RangeChecksumParams, ...client.CallOption) (*client.ObjectRangeHashRes, error)
|
|
||||||
ObjectSearchInit(context.Context, client.PrmObjectSearch) (*client.ObjectListReader, error)
|
ObjectSearchInit(context.Context, client.PrmObjectSearch) (*client.ObjectListReader, error)
|
||||||
AnnounceLocalTrust(context.Context, client.AnnounceLocalTrustPrm) (*client.AnnounceLocalTrustRes, error)
|
|
||||||
AnnounceIntermediateTrust(context.Context, client.AnnounceIntermediateTrustPrm) (*client.AnnounceIntermediateTrustRes, error)
|
|
||||||
CreateSession(context.Context, client.CreateSessionPrm) (*client.CreateSessionRes, error)
|
CreateSession(context.Context, client.CreateSessionPrm) (*client.CreateSessionRes, error)
|
||||||
|
|
||||||
Raw() *apiclient.Client
|
|
||||||
|
|
||||||
Conn() io.Closer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuilderOptions contains options used to build connection pool.
|
// BuilderOptions contains options used to build connection pool.
|
||||||
|
@ -162,12 +152,10 @@ type Pool interface {
|
||||||
|
|
||||||
type Object interface {
|
type Object interface {
|
||||||
PutObject(ctx context.Context, hdr object.Object, payload io.Reader, opts ...CallOption) (*oid.ID, error)
|
PutObject(ctx context.Context, hdr object.Object, payload io.Reader, opts ...CallOption) (*oid.ID, error)
|
||||||
DeleteObject(ctx context.Context, params *client.DeleteObjectParams, opts ...CallOption) error
|
DeleteObject(ctx context.Context, addr address.Address, opts ...CallOption) error
|
||||||
GetObject(context.Context, address.Address, ...CallOption) (*ResGetObject, error)
|
GetObject(context.Context, address.Address, ...CallOption) (*ResGetObject, error)
|
||||||
HeadObject(context.Context, address.Address, ...CallOption) (*object.Object, error)
|
HeadObject(context.Context, address.Address, ...CallOption) (*object.Object, error)
|
||||||
ObjectRange(ctx context.Context, addr address.Address, off, ln uint64, opts ...CallOption) (*ResObjectRange, error)
|
ObjectRange(ctx context.Context, addr address.Address, off, ln uint64, opts ...CallOption) (*ResObjectRange, error)
|
||||||
ObjectPayloadRangeSHA256(ctx context.Context, params *client.RangeChecksumParams, opts ...CallOption) ([][32]byte, error)
|
|
||||||
ObjectPayloadRangeTZ(ctx context.Context, params *client.RangeChecksumParams, opts ...CallOption) ([][64]byte, error)
|
|
||||||
SearchObjects(context.Context, cid.ID, object.SearchFilters, ...CallOption) (*ResObjectSearch, error)
|
SearchObjects(context.Context, cid.ID, object.SearchFilters, ...CallOption) (*ResObjectSearch, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,23 +805,37 @@ func (p *pool) PutObject(ctx context.Context, hdr object.Object, payload io.Read
|
||||||
return &id, nil
|
return &id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pool) DeleteObject(ctx context.Context, params *client.DeleteObjectParams, opts ...CallOption) error {
|
func (p *pool) DeleteObject(ctx context.Context, addr address.Address, opts ...CallOption) error {
|
||||||
cfg := cfgFromOpts(append(opts, useDefaultSession())...)
|
cfg := cfgFromOpts(append(opts, useDefaultSession())...)
|
||||||
cp, options, err := p.conn(ctx, cfg)
|
|
||||||
|
var prm client.PrmObjectDelete
|
||||||
|
|
||||||
|
var cc callContextWithRetry
|
||||||
|
|
||||||
|
cc.Context = ctx
|
||||||
|
cc.sessionTarget = prm.WithinSession
|
||||||
|
|
||||||
|
err := p.initCallContextWithRetry(&cc, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = cp.client.DeleteObject(ctx, params, options...)
|
if cnr := addr.ContainerID(); cnr != nil {
|
||||||
|
prm.FromContainer(*cnr)
|
||||||
if p.checkSessionTokenErr(err, cp.address) && !cfg.isRetry {
|
|
||||||
opts = append(opts, retry())
|
|
||||||
return p.DeleteObject(ctx, params, opts...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// here err already carries both status and client errors
|
if obj := addr.ObjectID(); obj != nil {
|
||||||
|
prm.ByID(*obj)
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return p.callWithRetry(&cc, func() error {
|
||||||
|
_, err := cc.client.ObjectDelete(ctx, prm)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("remove object via client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type objectReadCloser client.ObjectReader
|
type objectReadCloser client.ObjectReader
|
||||||
|
@ -1006,92 +1008,6 @@ func (p *pool) ObjectRange(ctx context.Context, addr address.Address, off, ln ui
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyRangeChecksumParams(prm *client.RangeChecksumParams) *client.RangeChecksumParams {
|
|
||||||
var prmCopy client.RangeChecksumParams
|
|
||||||
|
|
||||||
prmCopy.WithAddress(prm.Address())
|
|
||||||
prmCopy.WithSalt(prm.Salt())
|
|
||||||
prmCopy.WithRangeList(prm.RangeList()...)
|
|
||||||
|
|
||||||
return &prmCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *pool) ObjectPayloadRangeSHA256(ctx context.Context, params *client.RangeChecksumParams, opts ...CallOption) ([][32]byte, error) {
|
|
||||||
cfg := cfgFromOpts(append(opts, useDefaultSession())...)
|
|
||||||
cp, options, err := p.conn(ctx, cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: pretty bad approach but we should not mutate params through the pointer
|
|
||||||
// If non-SHA256 algo is set then we need to reset it.
|
|
||||||
params = copyRangeChecksumParams(params)
|
|
||||||
// SHA256 by default, no need to do smth
|
|
||||||
|
|
||||||
res, err := cp.client.HashObjectPayloadRanges(ctx, params, options...)
|
|
||||||
|
|
||||||
if p.checkSessionTokenErr(err, cp.address) && !cfg.isRetry {
|
|
||||||
opts = append(opts, retry())
|
|
||||||
return p.ObjectPayloadRangeSHA256(ctx, params, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil { // here err already carries both status and client errors
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cliHashes := res.Hashes()
|
|
||||||
|
|
||||||
hs := make([][sha256.Size]byte, len(cliHashes))
|
|
||||||
|
|
||||||
for i := range cliHashes {
|
|
||||||
if ln := len(cliHashes[i]); ln != sha256.Size {
|
|
||||||
return nil, fmt.Errorf("invalid SHA256 checksum size %d", ln)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(hs[i][:], cliHashes[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return hs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *pool) ObjectPayloadRangeTZ(ctx context.Context, params *client.RangeChecksumParams, opts ...CallOption) ([][64]byte, error) {
|
|
||||||
cfg := cfgFromOpts(append(opts, useDefaultSession())...)
|
|
||||||
cp, options, err := p.conn(ctx, cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: pretty bad approach but we should not mutate params through the pointer
|
|
||||||
// We need to set Tillich-Zemor algo.
|
|
||||||
params = copyRangeChecksumParams(params)
|
|
||||||
params.TZ()
|
|
||||||
|
|
||||||
res, err := cp.client.HashObjectPayloadRanges(ctx, params, options...)
|
|
||||||
|
|
||||||
if p.checkSessionTokenErr(err, cp.address) && !cfg.isRetry {
|
|
||||||
opts = append(opts, retry())
|
|
||||||
return p.ObjectPayloadRangeTZ(ctx, params, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil { // here err already carries both status and client errors
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cliHashes := res.Hashes()
|
|
||||||
|
|
||||||
hs := make([][client.TZSize]byte, len(cliHashes))
|
|
||||||
|
|
||||||
for i := range cliHashes {
|
|
||||||
if ln := len(cliHashes[i]); ln != client.TZSize {
|
|
||||||
return nil, fmt.Errorf("invalid TZ checksum size %d", ln)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(hs[i][:], cliHashes[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
return hs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResObjectSearch struct {
|
type ResObjectSearch struct {
|
||||||
r *client.ObjectListReader
|
r *client.ObjectListReader
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue