2022-02-07 20:27:56 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
|
2023-03-07 11:20:03 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
|
|
|
v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
2023-06-27 08:53:53 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer"
|
2023-03-07 11:20:03 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
2022-02-07 20:27:56 +00:00
|
|
|
)
|
|
|
|
|
2023-06-27 08:53:53 +00:00
|
|
|
// defaultGRPCPayloadChunkLen default value for maxChunkLen.
|
|
|
|
// See PrmObjectPutInit.SetGRPCPayloadChunkLen for details.
|
|
|
|
const defaultGRPCPayloadChunkLen = 3 << 20
|
|
|
|
|
2022-02-07 20:27:56 +00:00
|
|
|
// PrmObjectPutInit groups parameters of ObjectPutInit operation.
|
2022-07-29 15:42:24 +00:00
|
|
|
type PrmObjectPutInit struct {
|
2023-06-27 08:53:53 +00:00
|
|
|
copyNum []uint32
|
|
|
|
key *ecdsa.PrivateKey
|
|
|
|
meta v2session.RequestMetaHeader
|
|
|
|
maxChunkLen int
|
|
|
|
maxSize uint64
|
|
|
|
epochSource transformer.EpochSource
|
|
|
|
withoutHomomorphicHash bool
|
2022-07-29 15:42:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetCopiesNumber sets number of object copies that is enough to consider put successful.
|
|
|
|
func (x *PrmObjectPutInit) SetCopiesNumber(copiesNumber uint32) {
|
2023-04-07 15:40:54 +00:00
|
|
|
x.copyNum = []uint32{copiesNumber}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetCopiesNumberByVectors sets ordered list of minimal required object copies numbers
|
|
|
|
// per placement vector. List's length MUST equal container's placement vector number,
|
|
|
|
// otherwise request will fail.
|
|
|
|
func (x *PrmObjectPutInit) SetCopiesNumberByVectors(copiesNumbers []uint32) {
|
|
|
|
x.copyNum = copiesNumbers
|
2022-07-29 15:42:24 +00:00
|
|
|
}
|
2022-02-07 20:27:56 +00:00
|
|
|
|
2023-06-26 15:13:04 +00:00
|
|
|
// SetGRPCPayloadChunkLen sets maximum chunk length value for gRPC Put request.
|
|
|
|
// Maximum chunk length restricts maximum byte length of the chunk
|
|
|
|
// transmitted in a single stream message. It depends on
|
|
|
|
// server settings and other message fields.
|
|
|
|
// If not specified or negative value set, default value of 3MiB will be used.
|
|
|
|
func (x *PrmObjectPutInit) SetGRPCPayloadChunkLen(v int) {
|
|
|
|
x.maxChunkLen = v
|
|
|
|
}
|
|
|
|
|
2022-02-07 20:27:56 +00:00
|
|
|
// ResObjectPut groups the final result values of ObjectPutInit operation.
|
|
|
|
type ResObjectPut struct {
|
|
|
|
statusRes
|
|
|
|
|
2022-08-05 07:56:49 +00:00
|
|
|
obj oid.ID
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
2022-08-05 07:56:49 +00:00
|
|
|
// StoredObjectID returns identifier of the saved object.
|
|
|
|
func (x ResObjectPut) StoredObjectID() oid.ID {
|
|
|
|
return x.obj
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
2023-06-27 08:53:53 +00:00
|
|
|
// ObjectWriter is designed to write one object or
|
|
|
|
// multiple parts of one object to FrostFS system.
|
2022-02-07 20:27:56 +00:00
|
|
|
//
|
|
|
|
// Must be initialized using Client.ObjectPutInit, any other
|
|
|
|
// usage is unsafe.
|
2023-06-27 08:53:53 +00:00
|
|
|
type ObjectWriter interface {
|
|
|
|
// WriteHeader writes header of the object. Result means success.
|
|
|
|
// Failure reason can be received via Close.
|
|
|
|
WriteHeader(context.Context, object.Object) bool
|
|
|
|
// WritePayloadChunk writes chunk of the object payload. Result means success.
|
|
|
|
// Failure reason can be received via Close.
|
|
|
|
WritePayloadChunk(context.Context, []byte) bool
|
|
|
|
// Close ends writing the object and returns the result of the operation
|
|
|
|
// along with the final results. Must be called after using the ObjectWriter.
|
|
|
|
//
|
|
|
|
// 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 Go built-in error.
|
|
|
|
// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures
|
|
|
|
// codes are returned as error.
|
|
|
|
//
|
|
|
|
// Return statuses:
|
|
|
|
// - global (see Client docs);
|
|
|
|
// - *apistatus.ContainerNotFound;
|
|
|
|
// - *apistatus.ObjectAccessDenied;
|
|
|
|
// - *apistatus.ObjectLocked;
|
|
|
|
// - *apistatus.LockNonRegularObject;
|
|
|
|
// - *apistatus.SessionTokenNotFound;
|
|
|
|
// - *apistatus.SessionTokenExpired.
|
|
|
|
Close(context.Context) (*ResObjectPut, error)
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// UseKey specifies private key to sign the requests.
|
|
|
|
// If key is not provided, then Client default key is used.
|
2022-08-25 12:14:18 +00:00
|
|
|
func (x *PrmObjectPutInit) UseKey(key ecdsa.PrivateKey) {
|
|
|
|
x.key = &key
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// WithBearerToken attaches bearer token to be used for the operation.
|
|
|
|
// Should be called once before any writing steps.
|
2022-08-25 12:14:18 +00:00
|
|
|
func (x *PrmObjectPutInit) WithBearerToken(t bearer.Token) {
|
2022-03-24 08:05:41 +00:00
|
|
|
var v2token acl.BearerToken
|
|
|
|
t.WriteToV2(&v2token)
|
2022-08-25 12:14:18 +00:00
|
|
|
x.meta.SetBearerToken(&v2token)
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// WithinSession specifies session within which object should be stored.
|
|
|
|
// Should be called once before any writing steps.
|
2022-08-25 12:14:18 +00:00
|
|
|
func (x *PrmObjectPutInit) WithinSession(t session.Object) {
|
2022-04-07 16:09:15 +00:00
|
|
|
var tv2 v2session.Token
|
|
|
|
t.WriteToV2(&tv2)
|
|
|
|
|
2022-08-25 12:14:18 +00:00
|
|
|
x.meta.SetSessionToken(&tv2)
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MarkLocal tells the server to execute the operation locally.
|
2022-08-25 12:14:18 +00:00
|
|
|
func (x *PrmObjectPutInit) MarkLocal() {
|
|
|
|
x.meta.SetTTL(1)
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
2022-03-03 11:04:53 +00:00
|
|
|
// WithXHeaders specifies list of extended headers (string key-value pairs)
|
|
|
|
// to be attached to the request. Must have an even length.
|
|
|
|
//
|
|
|
|
// Slice must not be mutated until the operation completes.
|
2022-08-25 12:14:18 +00:00
|
|
|
func (x *PrmObjectPutInit) WithXHeaders(hs ...string) {
|
|
|
|
writeXHeadersToMeta(hs, &x.meta)
|
2022-03-03 11:04:53 +00:00
|
|
|
}
|
|
|
|
|
2023-06-27 08:53:53 +00:00
|
|
|
// WithObjectMaxSize specifies max object size value and use it during object splitting.
|
|
|
|
// When specified, start writing to the stream only after the object is formed.
|
|
|
|
// Continue processing the input only when the previous formed object has been successfully written.
|
|
|
|
func (x *PrmObjectPutInit) WithObjectMaxSize(maxSize uint64) {
|
|
|
|
x.maxSize = maxSize
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
2023-06-27 08:53:53 +00:00
|
|
|
// WithoutHomomorphicHash if set to true do not use Tillich-Zémor hash for payload.
|
|
|
|
func (x *PrmObjectPutInit) WithoutHomomorphicHash(v bool) {
|
|
|
|
x.withoutHomomorphicHash = v
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
2023-06-27 08:53:53 +00:00
|
|
|
// WithEpochSource specifies epoch for object when split it on client side.
|
|
|
|
func (x *PrmObjectPutInit) WithEpochSource(es transformer.EpochSource) {
|
|
|
|
x.epochSource = es
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|
|
|
|
|
2022-12-29 10:46:18 +00:00
|
|
|
// ObjectPutInit initiates writing an object through a remote server using FrostFS API protocol.
|
2022-02-07 20:27:56 +00:00
|
|
|
//
|
|
|
|
// The call only opens the transmission channel, explicit recording is done using the ObjectWriter.
|
|
|
|
// Exactly one return value is non-nil. Resulting writer must be finally closed.
|
|
|
|
//
|
2023-02-27 07:53:27 +00:00
|
|
|
// Returns an error if parameters are set incorrectly.
|
2022-02-07 20:27:56 +00:00
|
|
|
// Context is required and must not be nil. It is used for network communication.
|
2023-06-27 08:53:53 +00:00
|
|
|
func (c *Client) ObjectPutInit(ctx context.Context, prm PrmObjectPutInit) (ObjectWriter, error) {
|
|
|
|
if prm.maxSize > 0 {
|
|
|
|
return c.objectPutInitTransformer(prm)
|
2022-08-05 07:56:49 +00:00
|
|
|
}
|
2023-06-27 08:53:53 +00:00
|
|
|
return c.objectPutInitRaw(ctx, prm)
|
2022-02-07 20:27:56 +00:00
|
|
|
}
|