forked from TrueCloudLab/frostfs-sdk-java
parent
c9a54d56fb
commit
23bbe08893
70 changed files with 1375 additions and 587 deletions
|
@ -1,16 +1,16 @@
|
|||
package info.frostfs.sdk;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.SessionToken;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
|
||||
import info.frostfs.sdk.dto.netmap.NodeInfo;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.dto.object.ObjectFilter;
|
||||
import info.frostfs.sdk.dto.object.ObjectFrostFS;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.ClientSettings;
|
||||
import info.frostfs.sdk.jdo.NetworkSettings;
|
||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
|||
|
||||
import static info.frostfs.sdk.tools.GrpcClient.initGrpcChannel;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient {
|
||||
private static final String ERROR_CLIENT_OPTIONS_INIT = "Options must be initialized.";
|
||||
|
@ -39,9 +40,8 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
|
|||
throw new IllegalArgumentException(ERROR_CLIENT_OPTIONS_INIT);
|
||||
}
|
||||
|
||||
clientSettings.validate();
|
||||
|
||||
Channel channel = initGrpcChannel(clientSettings.getHost(), clientSettings.getCreds());
|
||||
Channel channel = nonNull(clientSettings.getChannel()) ? clientSettings.getChannel()
|
||||
: initGrpcChannel(clientSettings.getHost(), clientSettings.getCredentials());
|
||||
|
||||
ClientEnvironment clientEnvironment =
|
||||
new ClientEnvironment(clientSettings.getKey(), channel, new Version(), this);
|
||||
|
@ -98,13 +98,18 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
|
|||
return objectClientImpl.putObject(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putSingleObject(ObjectFrostFS objectFrostFS) {
|
||||
return objectClientImpl.putSingleObject(objectFrostFS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObject(ContainerId containerId, ObjectId objectId) {
|
||||
objectClientImpl.deleteObject(containerId, objectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters) {
|
||||
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) {
|
||||
return objectClientImpl.searchObjects(cid, filters);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package info.frostfs.sdk.enums;
|
||||
|
||||
public enum WaitExpects {
|
||||
EXISTS,
|
||||
REMOVED
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package info.frostfs.sdk.exceptions;
|
||||
|
||||
import info.frostfs.sdk.dto.response.ResponseStatus;
|
||||
|
||||
public class ResponseException extends RuntimeException {
|
||||
private final ResponseStatus status;
|
||||
|
||||
public ResponseException(ResponseStatus status) {
|
||||
super(status.toString());
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public ResponseStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package info.frostfs.sdk.exceptions;
|
||||
|
||||
public class TimeoutException extends RuntimeException {
|
||||
public TimeoutException() {
|
||||
}
|
||||
}
|
|
@ -1,14 +1,16 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
|
||||
import info.frostfs.sdk.FrostFSClient;
|
||||
import info.frostfs.sdk.dto.OwnerId;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
import io.grpc.Channel;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ClientEnvironment {
|
||||
private static final String ERROR_MESSAGE = "One of the input attributes is missing";
|
||||
|
||||
private final OwnerId ownerId;
|
||||
private final Version version;
|
||||
private final ECDsa key;
|
||||
|
@ -18,7 +20,7 @@ public class ClientEnvironment {
|
|||
|
||||
public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient) {
|
||||
if (StringUtils.isEmpty(wif) || isNull(channel) || isNull(version) || isNull(frostFSClient)) {
|
||||
throw new IllegalArgumentException("One of the input attributes is missing");
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
this.key = new ECDsa(wif);
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ChannelCredentials;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class ClientSettings {
|
||||
private static final String ERROR_TEMPLATE = "%s is required parameter.";
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public String key;
|
||||
public String host;
|
||||
public ChannelCredentials creds;
|
||||
public class ClientSettings {
|
||||
private static final String ERROR_TEMPLATE = "%s required parameter.";
|
||||
private static final String KEY_NAME = "Key";
|
||||
private static final String HOST_AND_CHANNEL_NAME = "Host or Channel";
|
||||
|
||||
private final String key;
|
||||
private String host;
|
||||
private ChannelCredentials credentials;
|
||||
private Channel channel;
|
||||
|
||||
public ClientSettings(String key, String host) {
|
||||
this.key = key;
|
||||
|
@ -16,46 +22,44 @@ public class ClientSettings {
|
|||
validate();
|
||||
}
|
||||
|
||||
public ClientSettings(String key, String host, ChannelCredentials creds) {
|
||||
public ClientSettings(String key, String host, ChannelCredentials credentials) {
|
||||
this.key = key;
|
||||
this.host = host;
|
||||
this.creds = creds;
|
||||
this.credentials = credentials;
|
||||
validate();
|
||||
}
|
||||
|
||||
public ChannelCredentials getCreds() {
|
||||
return creds;
|
||||
public ClientSettings(String key, Channel channel) {
|
||||
this.key = key;
|
||||
this.channel = channel;
|
||||
validate();
|
||||
}
|
||||
|
||||
public void setCreds(ChannelCredentials creds) {
|
||||
this.creds = creds;
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public ChannelCredentials getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
StringBuilder errorMessage = new StringBuilder();
|
||||
|
||||
if (StringUtils.isEmpty(key)) {
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, "Key")).append(System.lineSeparator());
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, KEY_NAME)).append(System.lineSeparator());
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(host)) {
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, "Host")).append(System.lineSeparator());
|
||||
if (StringUtils.isEmpty(host) && isNull(channel)) {
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, HOST_AND_CHANNEL_NAME)).append(System.lineSeparator());
|
||||
}
|
||||
|
||||
if (errorMessage.length() != 0) {
|
||||
|
|
|
@ -7,13 +7,15 @@ import java.security.PrivateKey;
|
|||
import static info.frostfs.sdk.KeyExtension.*;
|
||||
|
||||
public class ECDsa {
|
||||
private static final String ERROR_MESSAGE = "WIF is invalid";
|
||||
|
||||
private final byte[] publicKeyByte;
|
||||
private final byte[] privateKeyByte;
|
||||
private final PrivateKey privateKey;
|
||||
|
||||
public ECDsa(String wif) {
|
||||
if (StringUtils.isEmpty(wif)) {
|
||||
throw new IllegalArgumentException("Wif is invalid");
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
this.privateKeyByte = getPrivateKeyFromWIF(wif);
|
||||
|
|
|
@ -5,21 +5,21 @@ import java.util.Map;
|
|||
|
||||
public class NetworkSettings {
|
||||
|
||||
public Long auditFee;
|
||||
public Long basicIncomeRate;
|
||||
public Long containerFee;
|
||||
public Long containerAliasFee;
|
||||
public Long innerRingCandidateFee;
|
||||
public Long withdrawFee;
|
||||
public Long epochDuration;
|
||||
public Long iRCandidateFee;
|
||||
public Long maxObjectSize;
|
||||
public Long maxECDataCount;
|
||||
public Long maxECParityCount;
|
||||
public Long withdrawalFee;
|
||||
public Boolean homomorphicHashingDisabled;
|
||||
public Boolean maintenanceModeAllowed;
|
||||
public Map<String, Object> unnamedSettings = new HashMap<>();
|
||||
private Long auditFee;
|
||||
private Long basicIncomeRate;
|
||||
private Long containerFee;
|
||||
private Long containerAliasFee;
|
||||
private Long innerRingCandidateFee;
|
||||
private Long withdrawFee;
|
||||
private Long epochDuration;
|
||||
private Long iRCandidateFee;
|
||||
private Long maxObjectSize;
|
||||
private Long maxECDataCount;
|
||||
private Long maxECParityCount;
|
||||
private Long withdrawalFee;
|
||||
private Boolean homomorphicHashingDisabled;
|
||||
private Boolean maintenanceModeAllowed;
|
||||
private Map<String, Object> unnamedSettings = new HashMap<>();
|
||||
|
||||
public Long getAuditFee() {
|
||||
return auditFee;
|
||||
|
@ -77,11 +77,11 @@ public class NetworkSettings {
|
|||
this.epochDuration = epochDuration;
|
||||
}
|
||||
|
||||
public long getiRCandidateFee() {
|
||||
public long getIRCandidateFee() {
|
||||
return iRCandidateFee;
|
||||
}
|
||||
|
||||
public void setiRCandidateFee(long iRCandidateFee) {
|
||||
public void setIRCandidateFee(long iRCandidateFee) {
|
||||
this.iRCandidateFee = iRCandidateFee;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
|
||||
|
@ -8,11 +9,18 @@ import static java.util.Objects.isNull;
|
|||
|
||||
public class PutObjectParameters {
|
||||
private static final String ERROR_TEMPLATE = "%s value cannot be null.";
|
||||
private static final String HEADER_NAME = "Header";
|
||||
private static final String PAYLOAD_NAME = "Payload";
|
||||
|
||||
public ObjectHeader header;
|
||||
public FileInputStream payload;
|
||||
public boolean clientCut;
|
||||
public int bufferMaxSize;
|
||||
private ObjectHeader header;
|
||||
private FileInputStream payload;
|
||||
private boolean clientCut;
|
||||
private int bufferMaxSize;
|
||||
private byte[] customerBuffer;
|
||||
private SessionToken sessionToken;
|
||||
private int maxObjectSizeCache;
|
||||
private long currentStreamPosition;
|
||||
private long fullLength;
|
||||
|
||||
public PutObjectParameters(ObjectHeader header, FileInputStream payload, boolean clientCut, int bufferMaxSize) {
|
||||
this.header = header;
|
||||
|
@ -30,6 +38,46 @@ public class PutObjectParameters {
|
|||
validate();
|
||||
}
|
||||
|
||||
public byte[] getCustomerBuffer() {
|
||||
return customerBuffer;
|
||||
}
|
||||
|
||||
public void setCustomerBuffer(byte[] customerBuffer) {
|
||||
this.customerBuffer = customerBuffer;
|
||||
}
|
||||
|
||||
public SessionToken getSessionToken() {
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
public void setSessionToken(SessionToken sessionToken) {
|
||||
this.sessionToken = sessionToken;
|
||||
}
|
||||
|
||||
public int getMaxObjectSizeCache() {
|
||||
return maxObjectSizeCache;
|
||||
}
|
||||
|
||||
public void setMaxObjectSizeCache(int maxObjectSizeCache) {
|
||||
this.maxObjectSizeCache = maxObjectSizeCache;
|
||||
}
|
||||
|
||||
public long getCurrentStreamPosition() {
|
||||
return currentStreamPosition;
|
||||
}
|
||||
|
||||
public void setCurrentStreamPosition(long currentStreamPosition) {
|
||||
this.currentStreamPosition = currentStreamPosition;
|
||||
}
|
||||
|
||||
public long getFullLength() {
|
||||
return fullLength;
|
||||
}
|
||||
|
||||
public void setFullLength(long fullLength) {
|
||||
this.fullLength = fullLength;
|
||||
}
|
||||
|
||||
public ObjectHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
@ -66,11 +114,11 @@ public class PutObjectParameters {
|
|||
StringBuilder errorMessage = new StringBuilder();
|
||||
|
||||
if (isNull(header)) {
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, "Header")).append(System.lineSeparator());
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, HEADER_NAME)).append(System.lineSeparator());
|
||||
}
|
||||
|
||||
if (isNull(payload)) {
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, "Payload")).append(System.lineSeparator());
|
||||
errorMessage.append(String.format(ERROR_TEMPLATE, PAYLOAD_NAME)).append(System.lineSeparator());
|
||||
}
|
||||
|
||||
if (errorMessage.length() != 0) {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
|
||||
public class PutObjectResult {
|
||||
private final ObjectId objectId;
|
||||
private final int objectSize;
|
||||
|
||||
public PutObjectResult(ObjectId objectId, int objectSize) {
|
||||
this.objectId = objectId;
|
||||
this.objectSize = objectSize;
|
||||
}
|
||||
|
||||
public ObjectId getObjectId() {
|
||||
return objectId;
|
||||
}
|
||||
|
||||
public int getObjectSize() {
|
||||
return objectSize;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class WaitParameters {
|
||||
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(120);
|
||||
private static final Duration DEFAULT_POLL_INTERVAL = Duration.ofSeconds(5);
|
||||
|
||||
private final Duration timeout;
|
||||
private final Duration pollInterval;
|
||||
|
||||
public WaitParameters() {
|
||||
this.timeout = DEFAULT_TIMEOUT;
|
||||
this.pollInterval = DEFAULT_POLL_INTERVAL;
|
||||
}
|
||||
|
||||
public WaitParameters(Duration timeout, Duration pollInterval) {
|
||||
this.timeout = timeout;
|
||||
this.pollInterval = pollInterval;
|
||||
}
|
||||
|
||||
public Duration getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public Duration getPollInterval() {
|
||||
return pollInterval;
|
||||
}
|
||||
|
||||
public LocalDateTime getDeadline() {
|
||||
return LocalDateTime.now().plus(timeout);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,9 @@ public interface ObjectClient {
|
|||
|
||||
ObjectId putObject(PutObjectParameters parameters);
|
||||
|
||||
ObjectId putSingleObject(ObjectFrostFS objectFrostFS);
|
||||
|
||||
void deleteObject(ContainerId containerId, ObjectId objectId);
|
||||
|
||||
Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters);
|
||||
Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import info.frostfs.sdk.dto.SessionToken;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
|
||||
public interface SessionClient {
|
||||
SessionToken createSession(long expiration);
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
|
||||
public interface SessionTools {
|
||||
Types.SessionToken getOrCreateSession(SessionToken token, ClientEnvironment env);
|
||||
}
|
|
@ -2,48 +2,60 @@ package info.frostfs.sdk.services.impl;
|
|||
|
||||
import frostfs.container.ContainerServiceGrpc;
|
||||
import frostfs.container.Service;
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.enums.StatusCode;
|
||||
import info.frostfs.sdk.enums.WaitExpects;
|
||||
import info.frostfs.sdk.exceptions.ResponseException;
|
||||
import info.frostfs.sdk.exceptions.TimeoutException;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.mappers.OwnerIdMapper;
|
||||
import info.frostfs.sdk.mappers.VersionMapper;
|
||||
import info.frostfs.sdk.jdo.WaitParameters;
|
||||
import info.frostfs.sdk.mappers.container.ContainerIdMapper;
|
||||
import info.frostfs.sdk.mappers.container.ContainerMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.VersionMapper;
|
||||
import info.frostfs.sdk.mappers.object.OwnerIdMapper;
|
||||
import info.frostfs.sdk.services.ContainerClient;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.tools.RequestConstructor;
|
||||
import info.frostfs.sdk.tools.RequestSigner;
|
||||
import info.frostfs.sdk.tools.Verifier;
|
||||
import info.frostfs.sdk.utils.WaitUtil;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ContainerClientImpl extends ContextAccessor implements ContainerClient {
|
||||
private static final String ERROR_CONTAINER_ID_MISSING = "ContainerId is not present";
|
||||
private static final String ERROR_CONTAINER_MISSING = "Container is not present";
|
||||
|
||||
private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;
|
||||
private final SessionToolsImpl sessionTools;
|
||||
|
||||
public ContainerClientImpl(ClientEnvironment clientEnvironment) {
|
||||
super(clientEnvironment);
|
||||
this.serviceBlockingStub = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel());
|
||||
this.sessionTools = new SessionToolsImpl(clientEnvironment);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) {
|
||||
return sessionTools.getOrCreateSession(sessionToken, getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container getContainer(ContainerId cid) {
|
||||
if (isNull(cid)) {
|
||||
throw new IllegalArgumentException("ContainerId is not present");
|
||||
throw new IllegalArgumentException(ERROR_CONTAINER_ID_MISSING);
|
||||
}
|
||||
|
||||
var body = Service.GetRequest.Body.newBuilder()
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
|
||||
.build();
|
||||
var request = Service.GetRequest.newBuilder()
|
||||
.setBody(body);
|
||||
var request = createGetRequest(ContainerIdMapper.toGrpcMessage(cid), null);
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
var response = serviceBlockingStub.get(request.build());
|
||||
var response = serviceBlockingStub.get(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
return ContainerMapper.toModel(response.getBody().getContainer());
|
||||
|
@ -51,16 +63,9 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
|
||||
@Override
|
||||
public List<ContainerId> listContainers() {
|
||||
var body = Service.ListRequest.Body.newBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.build();
|
||||
var request = Service.ListRequest.newBuilder()
|
||||
.setBody(body);
|
||||
var request = createListRequest(null);
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
var response = serviceBlockingStub.list(request.build());
|
||||
var response = serviceBlockingStub.list(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
|
@ -72,51 +77,155 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
@Override
|
||||
public ContainerId createContainer(Container container) {
|
||||
if (isNull(container)) {
|
||||
throw new IllegalArgumentException("Container is not present");
|
||||
throw new IllegalArgumentException(ERROR_CONTAINER_MISSING);
|
||||
}
|
||||
|
||||
var grpcContainer = ContainerMapper.toGrpcMessage(container);
|
||||
grpcContainer = grpcContainer.toBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
|
||||
.build();
|
||||
var request = createPutRequest(grpcContainer, null);
|
||||
|
||||
var body = Service.PutRequest.Body.newBuilder()
|
||||
.setContainer(grpcContainer)
|
||||
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), grpcContainer))
|
||||
.build();
|
||||
var request = Service.PutRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
var response = serviceBlockingStub.put(request.build());
|
||||
var response = serviceBlockingStub.put(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
waitForContainer(WaitExpects.EXISTS, response.getBody().getContainerId(), null);
|
||||
|
||||
return new ContainerId(response.getBody().getContainerId().getValue().toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContainer(ContainerId cid) {
|
||||
if (isNull(cid)) {
|
||||
throw new IllegalArgumentException("ContainerId is not present");
|
||||
throw new IllegalArgumentException(ERROR_CONTAINER_ID_MISSING);
|
||||
}
|
||||
|
||||
var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid);
|
||||
var request = createDeleteRequest(grpcContainerId, null);
|
||||
|
||||
var response = serviceBlockingStub.delete(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
waitForContainer(WaitExpects.REMOVED, request.getBody().getContainerId(), null);
|
||||
}
|
||||
|
||||
private void waitForContainer(WaitExpects expect, Types.ContainerID id, WaitParameters waitParams) {
|
||||
var request = createGetRequest(id, null);
|
||||
|
||||
waitParams = isNull(waitParams) ? new WaitParameters() : waitParams;
|
||||
var deadLine = waitParams.getDeadline();
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
var response = serviceBlockingStub.get(request);
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
if (expect == WaitExpects.EXISTS) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (LocalDateTime.now().isAfter(deadLine)) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
|
||||
WaitUtil.sleep(waitParams.getPollInterval().toMillis());
|
||||
} catch (ResponseException exp) {
|
||||
if (LocalDateTime.now().isAfter(deadLine)) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
|
||||
if (exp.getStatus().getCode() != StatusCode.CONTAINER_NOT_FOUND) {
|
||||
throw exp;
|
||||
}
|
||||
|
||||
if (expect == WaitExpects.REMOVED) {
|
||||
break;
|
||||
}
|
||||
|
||||
WaitUtil.sleep(waitParams.getPollInterval().toMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Service.GetRequest createGetRequest(Types.ContainerID cid,
|
||||
Map<String, String> xHeaders) {
|
||||
var body = Service.GetRequest.Body.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.build();
|
||||
var request = Service.GetRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.ListRequest createListRequest(Map<String, String> xHeaders) {
|
||||
var body = Service.ListRequest.Body.newBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.build();
|
||||
var request = Service.ListRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.PutRequest createPutRequest(frostfs.container.Types.Container container,
|
||||
Map<String, String> xHeaders) {
|
||||
container = container.toBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
|
||||
.build();
|
||||
|
||||
var body = Service.PutRequest.Body.newBuilder()
|
||||
.setContainer(container)
|
||||
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), container))
|
||||
.build();
|
||||
var request = Service.PutRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createContainerTokenContext(
|
||||
sessionToken,
|
||||
null,
|
||||
frostfs.session.Types.ContainerSessionContext.Verb.PUT,
|
||||
container.getOwnerId(),
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders, sessionToken);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.DeleteRequest createDeleteRequest(Types.ContainerID cid,
|
||||
Map<String, String> xHeaders) {
|
||||
var body = Service.DeleteRequest.Body.newBuilder()
|
||||
.setContainerId(grpcContainerId)
|
||||
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), grpcContainerId.getValue()))
|
||||
.setContainerId(cid)
|
||||
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), cid.getValue()))
|
||||
.build();
|
||||
var request = Service.DeleteRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createContainerTokenContext(
|
||||
sessionToken,
|
||||
null,
|
||||
frostfs.session.Types.ContainerSessionContext.Verb.DELETE,
|
||||
null,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders, sessionToken);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
var response = serviceBlockingStub.delete(request.build());
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
return request.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
settings.setEpochDuration(getLongValue(valueBytes));
|
||||
break;
|
||||
case "InnerRingCandidateFee":
|
||||
settings.setiRCandidateFee(getLongValue(valueBytes));
|
||||
settings.setIRCandidateFee(getLongValue(valueBytes));
|
||||
break;
|
||||
case "MaxECDataCount":
|
||||
settings.setMaxECDataCount(getLongValue(valueBytes));
|
||||
|
@ -114,10 +114,9 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
|
||||
@Override
|
||||
public NodeInfo getLocalNodeInfo() {
|
||||
var request = Service.LocalNodeInfoRequest.newBuilder()
|
||||
.setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build());
|
||||
var request = Service.LocalNodeInfoRequest.newBuilder();
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = netmapServiceClient.localNodeInfo(request.build());
|
||||
|
@ -127,10 +126,9 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
}
|
||||
|
||||
public Service.NetworkInfoResponse getNetworkInfo() {
|
||||
var request = Service.NetworkInfoRequest.newBuilder()
|
||||
.setBody(Service.NetworkInfoRequest.Body.newBuilder().build());
|
||||
var request = Service.NetworkInfoRequest.newBuilder();
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = netmapServiceClient.networkInfo(request.build());
|
||||
|
@ -142,10 +140,9 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
|
||||
@Override
|
||||
public NetmapSnapshot getNetmapSnapshot() {
|
||||
var request = Service.NetmapSnapshotRequest.newBuilder()
|
||||
.setBody(Service.NetmapSnapshotRequest.Body.newBuilder().build());
|
||||
var request = Service.NetmapSnapshotRequest.newBuilder();
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = netmapServiceClient.netmapSnapshot(request.build());
|
||||
|
|
|
@ -6,21 +6,22 @@ import frostfs.object.ObjectServiceGrpc;
|
|||
import frostfs.object.Service;
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.constants.AppConst;
|
||||
import info.frostfs.sdk.dto.Split;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.*;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.PutObjectParameters;
|
||||
import info.frostfs.sdk.mappers.OwnerIdMapper;
|
||||
import info.frostfs.sdk.mappers.VersionMapper;
|
||||
import info.frostfs.sdk.jdo.PutObjectResult;
|
||||
import info.frostfs.sdk.mappers.container.ContainerIdMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectFilterMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectFrostFSMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectHeaderMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectIdMapper;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.services.ObjectClient;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectReader;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectReaderImpl;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.SearchReader;
|
||||
import info.frostfs.sdk.tools.RequestConstructor;
|
||||
|
@ -30,44 +31,42 @@ import org.apache.commons.collections4.CollectionUtils;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static info.frostfs.sdk.Helper.getSha256;
|
||||
import static info.frostfs.sdk.tools.RequestConstructor.addObjectSessionToken;
|
||||
import static info.frostfs.sdk.tools.RequestSigner.sign;
|
||||
import static java.util.Objects.nonNull;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
||||
private static final String ERROR_PAYLOAD = "PayloadLength must be specified";
|
||||
private static final String ERROR_PARAMS_MISSING = "Params is not present";
|
||||
|
||||
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
|
||||
private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient;
|
||||
private final ObjectToolsImpl objectToolsImpl;
|
||||
private final SessionToolsImpl sessionTools;
|
||||
|
||||
public ObjectClientImpl(ClientEnvironment clientEnvironment) {
|
||||
super(clientEnvironment);
|
||||
this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(getContext().getChannel());
|
||||
this.objectServiceClient = ObjectServiceGrpc.newStub(getContext().getChannel());
|
||||
this.objectToolsImpl = new ObjectToolsImpl(clientEnvironment);
|
||||
this.sessionTools = new SessionToolsImpl(clientEnvironment);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) {
|
||||
return sessionTools.getOrCreateSession(sessionToken, getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
|
||||
.setObjectId(ObjectIdMapper.toGrpcMessage(oid))
|
||||
.build();
|
||||
var body = Service.HeadRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.build();
|
||||
var request = Service.HeadRequest.newBuilder()
|
||||
.setBody(body);
|
||||
if (isNull(cid) || isNull(oid)) {
|
||||
throw new IllegalArgumentException(ERROR_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
var request = createHeadRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
|
||||
|
||||
var response = objectServiceBlockingClient.head(request);
|
||||
|
||||
var response = objectServiceBlockingClient.head(request.build());
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return ObjectHeaderMapper.toModel(response.getBody().getHeader().getHeader());
|
||||
|
@ -75,66 +74,25 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
|
||||
@Override
|
||||
public ObjectFrostFS getObject(ContainerId cid, ObjectId oid) {
|
||||
var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1);
|
||||
var request = createGetRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
|
||||
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
|
||||
.setObjectId(ObjectIdMapper.toGrpcMessage(oid))
|
||||
.build();
|
||||
var body = Service.GetRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.build();
|
||||
var request = Service.GetRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
addObjectSessionToken(
|
||||
request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid),
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.GET, getContext().getKey()
|
||||
);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var obj = getObject(request.build());
|
||||
return ObjectFrostFSMapper.toModel(obj);
|
||||
return getObject(request);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteObject(ContainerId cid, ObjectId oid) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
|
||||
.setObjectId(ObjectIdMapper.toGrpcMessage(oid))
|
||||
.build();
|
||||
var body = Service.DeleteRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.build();
|
||||
var request = Service.DeleteRequest.newBuilder()
|
||||
.setBody(body);
|
||||
var request = createDeleteRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
var response = objectServiceBlockingClient.delete(request);
|
||||
|
||||
var response = objectServiceBlockingClient.delete(request.build());
|
||||
Verifier.checkResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters) {
|
||||
var body = Service.SearchRequest.Body.newBuilder()
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
|
||||
.setVersion(1);// TODO: clarify this param
|
||||
var request = createSearchRequest(ContainerIdMapper.toGrpcMessage(cid), filters);
|
||||
|
||||
for (ObjectFilter filter : filters) {
|
||||
body.addFilters(ObjectFilterMapper.toGrpcMessage(filter));
|
||||
}
|
||||
|
||||
var request = Service.SearchRequest.newBuilder()
|
||||
.setBody(body.build());
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var objectsIds = searchObjects(request.build());
|
||||
var objectsIds = searchObjects(request);
|
||||
|
||||
return Iterables.transform(objectsIds, input -> new ObjectId(input.getValue().toByteArray()));
|
||||
}
|
||||
|
@ -143,179 +101,188 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
public ObjectId putObject(PutObjectParameters parameters) {
|
||||
parameters.validate();
|
||||
|
||||
return parameters.clientCut ? putClientCutObject(parameters) : putStreamObject(parameters);
|
||||
if (parameters.isClientCut()) {
|
||||
return putClientCutObject(parameters);
|
||||
}
|
||||
|
||||
public ObjectId putSingleObject(ObjectFrostFS modelObject) {
|
||||
var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1);
|
||||
if (parameters.getHeader().getPayloadLength() > 0) {
|
||||
parameters.setFullLength(parameters.getHeader().getPayloadLength());
|
||||
} else {
|
||||
parameters.setFullLength(getStreamSize(parameters.getPayload()));
|
||||
}
|
||||
|
||||
return putStreamObject(parameters).getObjectId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putSingleObject(ObjectFrostFS modelObject) {
|
||||
var grpcObject = objectToolsImpl.createObject(modelObject);
|
||||
|
||||
var request = Service.PutSingleRequest.newBuilder()
|
||||
.setBody(Service.PutSingleRequest.Body.newBuilder().setObject(grpcObject).build());
|
||||
var request = createPutSingleRequest(grpcObject);
|
||||
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
addObjectSessionToken(
|
||||
request, sessionToken, grpcObject.getHeader().getContainerId(), grpcObject.getObjectId(),
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey()
|
||||
);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = objectServiceBlockingClient.putSingle(request.build());
|
||||
var response = objectServiceBlockingClient.putSingle(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return new ObjectId(grpcObject.getObjectId().getValue().toByteArray());
|
||||
}
|
||||
|
||||
private frostfs.object.Types.Object getObject(Service.GetRequest request) {
|
||||
var iterator = getObjectInit(request);
|
||||
var obj = iterator.readHeader();
|
||||
var payload = new byte[Math.toIntExact(obj.getHeader().getPayloadLength())];
|
||||
var offset = 0;
|
||||
var chunk = iterator.readChunk();
|
||||
private ObjectFrostFS getObject(Service.GetRequest request) {
|
||||
var reader = getObjectInit(request);
|
||||
|
||||
while (nonNull(chunk)) {
|
||||
System.arraycopy(chunk, 0, payload, offset, chunk.length);
|
||||
offset += chunk.length;
|
||||
chunk = iterator.readChunk();
|
||||
var grpcObject = reader.readHeader();
|
||||
var modelObject = ObjectFrostFSMapper.toModel(grpcObject);
|
||||
|
||||
modelObject.setObjectReader(reader);
|
||||
|
||||
return modelObject;
|
||||
}
|
||||
|
||||
return obj.toBuilder().setPayload(ByteString.copyFrom(payload)).build();
|
||||
}
|
||||
|
||||
private ObjectReader getObjectInit(Service.GetRequest initRequest) {
|
||||
private ObjectReaderImpl getObjectInit(Service.GetRequest initRequest) {
|
||||
if (initRequest.getSerializedSize() == 0) {
|
||||
throw new IllegalArgumentException(initRequest.getClass().getName());
|
||||
}
|
||||
|
||||
return new ObjectReader(objectServiceBlockingClient.get(initRequest));
|
||||
return new ObjectReaderImpl(objectServiceBlockingClient.get(initRequest));
|
||||
}
|
||||
|
||||
private ObjectId putStreamObject(PutObjectParameters parameters) {
|
||||
var header = parameters.getHeader();
|
||||
private PutObjectResult putStreamObject(PutObjectParameters parameters) {
|
||||
var chunkSize = parameters.getBufferMaxSize() > 0 ? parameters.getBufferMaxSize() : AppConst.OBJECT_CHUNK_SIZE;
|
||||
|
||||
var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1);
|
||||
var restBytes = parameters.getFullLength() - parameters.getCurrentStreamPosition();
|
||||
|
||||
var hdr = ObjectHeaderMapper.toGrpcMessage(header);
|
||||
hdr = hdr.toBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
|
||||
.build();
|
||||
chunkSize = (int) Math.min(restBytes, chunkSize);
|
||||
|
||||
var oid = Types.ObjectID.newBuilder().setValue(getSha256(hdr)).build();
|
||||
byte[] chunkBuffer = parameters.getCustomerBuffer() != null
|
||||
? parameters.getCustomerBuffer()
|
||||
: new byte[chunkSize];//todo change to pool
|
||||
|
||||
var initRequest = Service.PutRequest.newBuilder()
|
||||
.setBody(
|
||||
Service.PutRequest.Body.newBuilder()
|
||||
.setInit(
|
||||
Service.PutRequest.Body.Init.newBuilder().setHeader(hdr).build()
|
||||
).build()
|
||||
);
|
||||
var sentBytes = 0;
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(initRequest);
|
||||
addObjectSessionToken(
|
||||
initRequest, sessionToken, hdr.getContainerId(), oid,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey()
|
||||
);
|
||||
sign(initRequest, getContext().getKey());
|
||||
// 0 means no limit from client, so server side cut is performed
|
||||
var objectLimitSize = parameters.isClientCut() ? parameters.getMaxObjectSizeCache() : 0;
|
||||
|
||||
var stream = getUploadStream(parameters);
|
||||
|
||||
var writer = putObjectInit(initRequest.build());
|
||||
while (objectLimitSize == 0 || sentBytes < objectLimitSize) {
|
||||
// send chunks limited to default or user's settings
|
||||
var bufferSize = objectLimitSize > 0 ? Math.min(objectLimitSize - sentBytes, chunkSize) : chunkSize;
|
||||
|
||||
var bufferSize = parameters.getBufferMaxSize() > 0 ? parameters.getBufferMaxSize() : AppConst.OBJECT_CHUNK_SIZE;
|
||||
bufferSize = (int) Math.min(getStreamSize(parameters.getPayload()), bufferSize);
|
||||
bufferSize = header.getPayloadLength() > 0 ? (int) Math.min(header.getPayloadLength(), bufferSize) : bufferSize;
|
||||
var bytesCount = readNBytes(parameters.getPayload(), chunkBuffer, bufferSize);
|
||||
|
||||
var buffer = new byte[bufferSize];
|
||||
while (true) {
|
||||
var bytesCount = readNBytes(parameters.getPayload(), buffer, bufferSize);
|
||||
if (bytesCount <= 0) {
|
||||
if (bytesCount == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
var chunkRequest = Service.PutRequest.newBuilder(initRequest.build())
|
||||
.setBody(
|
||||
Service.PutRequest.Body.newBuilder()
|
||||
.setChunk(ByteString.copyFrom(Arrays.copyOfRange(buffer, 0, bytesCount)))
|
||||
.build()
|
||||
)
|
||||
sentBytes += bytesCount;
|
||||
|
||||
var body = Service.PutRequest.Body.newBuilder()
|
||||
.setChunk(ByteString.copyFrom(chunkBuffer, 0, bytesCount))
|
||||
.build();
|
||||
var chunkRequest = Service.PutRequest.newBuilder()
|
||||
.setBody(body)
|
||||
.clearVerifyHeader();
|
||||
|
||||
sign(chunkRequest, getContext().getKey());
|
||||
writer.write(chunkRequest.build());
|
||||
|
||||
stream.write(chunkRequest.build());
|
||||
}
|
||||
|
||||
var response = writer.complete();
|
||||
var response = stream.complete();
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return new ObjectId(response.getBody().getObjectId().getValue().toByteArray());
|
||||
var objectId = new ObjectId(response.getBody().getObjectId().getValue().toByteArray());
|
||||
return new PutObjectResult(objectId, sentBytes);
|
||||
}
|
||||
|
||||
private ObjectId putClientCutObject(PutObjectParameters parameters) {
|
||||
var header = parameters.getHeader();
|
||||
var tokenRaw = getOrCreateSession(parameters.getSessionToken());
|
||||
var token = new SessionToken(SessionMapper.serialize(tokenRaw));
|
||||
parameters.setSessionToken(token);
|
||||
|
||||
var fullLength = header.getPayloadLength() == 0
|
||||
? getStreamSize(parameters.getPayload())
|
||||
: header.getPayloadLength();
|
||||
|
||||
parameters.setFullLength(fullLength);
|
||||
|
||||
if (parameters.getMaxObjectSizeCache() == 0) {
|
||||
var networkSettings = getContext().getFrostFSClient().getNetworkSettings();
|
||||
var payloadSize = getStreamSize(parameters.getPayload());
|
||||
var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize());
|
||||
var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength();
|
||||
if (fullLength == 0) {
|
||||
throw new IllegalArgumentException(ERROR_PAYLOAD);
|
||||
parameters.setMaxObjectSizeCache((int) networkSettings.getMaxObjectSize());
|
||||
}
|
||||
|
||||
var buffer = new byte[objectSize];
|
||||
var largeObject = new LargeObject(header.getContainerId());
|
||||
var split = new Split();
|
||||
var restBytes = fullLength - parameters.getCurrentStreamPosition();
|
||||
var objectSize = restBytes > 0
|
||||
? Math.min(parameters.getMaxObjectSizeCache(), restBytes)
|
||||
: parameters.getMaxObjectSizeCache();
|
||||
|
||||
ObjectId objectId;
|
||||
List<ObjectId> sentObjectIds = new ArrayList<>();
|
||||
ObjectFrostFS currentObject;
|
||||
//define collection capacity
|
||||
var restPart = (restBytes % objectSize) > 0 ? 1 : 0;
|
||||
var objectsCount = fullLength > 0 ? (int) (restBytes / objectSize) + restPart : 0;
|
||||
|
||||
while (true) {
|
||||
var bytesCount = readNBytes(parameters.getPayload(), buffer, objectSize);
|
||||
List<ObjectId> sentObjectIds = new ArrayList<>(objectsCount);
|
||||
|
||||
// keep attributes for the large object
|
||||
var attributes = parameters.getHeader().getAttributes();
|
||||
|
||||
Split split = new Split();
|
||||
parameters.getHeader().setSplit(split);
|
||||
parameters.getHeader().setAttributes(new ArrayList<>());
|
||||
|
||||
// send all parts except the last one as separate Objects
|
||||
while (restBytes > (long) parameters.getMaxObjectSizeCache()) {
|
||||
var previous = CollectionUtils.isNotEmpty(sentObjectIds)
|
||||
? sentObjectIds.get(sentObjectIds.size() - 1)
|
||||
: null;
|
||||
split.setPrevious(previous);
|
||||
|
||||
var result = putStreamObject(parameters);
|
||||
|
||||
sentObjectIds.add(result.getObjectId());
|
||||
|
||||
restBytes -= result.getObjectSize();
|
||||
}
|
||||
|
||||
// send the last part and create linkObject
|
||||
if (CollectionUtils.isNotEmpty(sentObjectIds)) {
|
||||
split.setPrevious(sentObjectIds.get(sentObjectIds.size() - 1));
|
||||
}
|
||||
var largeObjectHeader =
|
||||
new ObjectHeader(header.getContainerId(), ObjectType.REGULAR, attributes, fullLength, null);
|
||||
|
||||
largeObject.appendBlock(buffer, bytesCount);
|
||||
split.setParentHeader(largeObjectHeader);
|
||||
|
||||
currentObject = new ObjectFrostFS(
|
||||
header.getContainerId(),
|
||||
bytesCount < objectSize ? Arrays.copyOfRange(buffer, 0, bytesCount) : buffer
|
||||
);
|
||||
currentObject.setSplit(split);
|
||||
var result = putStreamObject(parameters);
|
||||
|
||||
if (largeObject.getPayloadLength() == fullLength) {
|
||||
break;
|
||||
}
|
||||
sentObjectIds.add(result.getObjectId());
|
||||
|
||||
objectId = putSingleObject(currentObject);
|
||||
|
||||
sentObjectIds.add(objectId);
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(sentObjectIds)) {
|
||||
currentObject.addAttributes(parameters.getHeader().getAttributes());
|
||||
return putSingleObject(currentObject);
|
||||
}
|
||||
|
||||
largeObject.addAttributes(parameters.getHeader().getAttributes());
|
||||
largeObject.calculateHash();
|
||||
|
||||
currentObject.setParent(largeObject);
|
||||
|
||||
objectId = putSingleObject(currentObject);
|
||||
|
||||
sentObjectIds.add(objectId);
|
||||
|
||||
var linkObject = new LinkObject(header.getContainerId(), split.getSplitId(), largeObject);
|
||||
var linkObject = new LinkObject(header.getContainerId(), split.getSplitId(), largeObjectHeader);
|
||||
linkObject.addChildren(sentObjectIds);
|
||||
|
||||
linkObject.getHeader().getAttributes().clear();
|
||||
|
||||
putSingleObject(linkObject);
|
||||
|
||||
return objectToolsImpl.calculateObjectId(largeObject.getHeader());
|
||||
return split.getParent();
|
||||
}
|
||||
|
||||
// We are here if the payload is placed to one Object. It means no cut action, just simple PUT.
|
||||
var singlePartResult = putStreamObject(parameters);
|
||||
|
||||
return singlePartResult.getObjectId();
|
||||
}
|
||||
|
||||
private ObjectWriter getUploadStream(PutObjectParameters parameters) {
|
||||
var header = parameters.getHeader();
|
||||
|
||||
header.setOwnerId(getContext().getOwnerId());
|
||||
header.setVersion(getContext().getVersion());
|
||||
|
||||
var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header);
|
||||
grpcHeader = objectToolsImpl.updateSplitValues(grpcHeader, header.getSplit());
|
||||
|
||||
var oid = Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build();
|
||||
|
||||
var initRequest = createInitPutRequest(oid, grpcHeader);
|
||||
|
||||
return putObjectInit(initRequest);
|
||||
}
|
||||
|
||||
private ObjectWriter putObjectInit(Service.PutRequest initRequest) {
|
||||
|
@ -333,12 +300,12 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
var ids = reader.read();
|
||||
List<Types.ObjectID> result = new ArrayList<>();
|
||||
|
||||
while (nonNull(ids) && !ids.isEmpty()) {
|
||||
while (CollectionUtils.isNotEmpty(ids)) {
|
||||
result.addAll(ids);
|
||||
ids = reader.read();
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;//todo return yield
|
||||
}
|
||||
|
||||
private SearchReader getSearchReader(Service.SearchRequest initRequest) {
|
||||
|
@ -364,4 +331,168 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
throw new IllegalArgumentException(exp.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Service.HeadRequest createHeadRequest(Types.ContainerID cid, Types.ObjectID oid) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setObjectId(oid)
|
||||
.build();
|
||||
var body = Service.HeadRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.build();
|
||||
var request = Service.HeadRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.HEAD,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.GetRequest createGetRequest(Types.ContainerID cid, Types.ObjectID oid) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setObjectId(oid)
|
||||
.build();
|
||||
var body = Service.GetRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.build();
|
||||
var request = Service.GetRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.GET,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.DeleteRequest createDeleteRequest(Types.ContainerID cid, Types.ObjectID oid) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setObjectId(oid)
|
||||
.build();
|
||||
var body = Service.DeleteRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.build();
|
||||
var request = Service.DeleteRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.DELETE,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.SearchRequest createSearchRequest(Types.ContainerID cid, ObjectFilter<?>... filters) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.build();
|
||||
|
||||
var body = Service.SearchRequest.Body.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setVersion(1);// TODO: clarify this param
|
||||
|
||||
for (ObjectFilter<?> filter : filters) {
|
||||
body.addFilters(ObjectFilterMapper.toGrpcMessage(filter));
|
||||
}
|
||||
|
||||
var request = Service.SearchRequest.newBuilder()
|
||||
.setBody(body.build());
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.SEARCH,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.PutRequest createInitPutRequest(Types.ObjectID oid, frostfs.object.Types.Header header) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(header.getContainerId())
|
||||
.setObjectId(oid)
|
||||
.build();
|
||||
var init = Service.PutRequest.Body.Init.newBuilder()
|
||||
.setHeader(header)
|
||||
.build();
|
||||
var body = Service.PutRequest.Body.newBuilder()
|
||||
.setInit(init)
|
||||
.build();
|
||||
var request = Service.PutRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.PUT,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.PutSingleRequest createPutSingleRequest(frostfs.object.Types.Object grpcObject) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(grpcObject.getHeader().getContainerId())
|
||||
.setObjectId(grpcObject.getObjectId())
|
||||
.build();
|
||||
var body = Service.PutSingleRequest.Body.newBuilder()
|
||||
.setObject(grpcObject)
|
||||
.build();
|
||||
var request = Service.PutSingleRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.PUT,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,17 +5,21 @@ import frostfs.object.Types;
|
|||
import info.frostfs.sdk.dto.object.ObjectFrostFS;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.object.Split;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.mappers.OwnerIdMapper;
|
||||
import info.frostfs.sdk.mappers.VersionMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.VersionMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectHeaderMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectIdMapper;
|
||||
import info.frostfs.sdk.mappers.object.OwnerIdMapper;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.services.ToolsClient;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static info.frostfs.sdk.Helper.getSha256;
|
||||
import static info.frostfs.sdk.tools.RequestSigner.signData;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class ObjectToolsImpl extends ContextAccessor implements ToolsClient {
|
||||
|
@ -34,52 +38,29 @@ public class ObjectToolsImpl extends ContextAccessor implements ToolsClient {
|
|||
public ObjectId calculateObjectId(ObjectHeader header) {
|
||||
var grpcHeader = createHeader(header, new byte[]{});
|
||||
|
||||
if (nonNull(header.getSplit())) {
|
||||
grpcHeader = updateSplitValues(grpcHeader, header.getSplit());
|
||||
}
|
||||
|
||||
return ObjectIdMapper.toModel(
|
||||
frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build()
|
||||
);
|
||||
}
|
||||
|
||||
public Types.Object createObject(ObjectFrostFS objectFrostFs) {
|
||||
var grpcHeaderBuilder = ObjectHeaderMapper.toGrpcMessage(objectFrostFs.getHeader()).toBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
|
||||
.setPayloadLength(objectFrostFs.getPayload().length)
|
||||
.setPayloadHash(sha256Checksum(objectFrostFs.getPayload()));
|
||||
objectFrostFs.getHeader().setOwnerId(getContext().getOwnerId());
|
||||
objectFrostFs.getHeader().setVersion(getContext().getVersion());
|
||||
objectFrostFs.getHeader().setPayloadLength(objectFrostFs.getPayload().length);
|
||||
|
||||
var grpcHeader = ObjectHeaderMapper.toGrpcMessage(objectFrostFs.getHeader()).toBuilder()
|
||||
.setPayloadHash(sha256Checksum(objectFrostFs.getPayload()))
|
||||
.build();
|
||||
|
||||
var split = objectFrostFs.getHeader().getSplit();
|
||||
if (nonNull(split)) {
|
||||
var splitGrpc = Types.Header.Split.newBuilder()
|
||||
.setSplitId(
|
||||
nonNull(split.getSplitId())
|
||||
? ByteString.copyFrom(split.getSplitId().toBinary())
|
||||
: null
|
||||
);
|
||||
|
||||
ListUtils.emptyIfNull(split.getChildren()).stream()
|
||||
.map(ObjectIdMapper::toGrpcMessage)
|
||||
.forEach(splitGrpc::addChildren);
|
||||
|
||||
|
||||
if (nonNull(split.getParentHeader())) {
|
||||
var grpcParentHeader = createHeader(split.getParentHeader(), new byte[]{});
|
||||
var parent = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcParentHeader)).build();
|
||||
var parentSig = frostfs.refs.Types.Signature.newBuilder()
|
||||
.setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte()))
|
||||
.setSign(ByteString.copyFrom(signData(getContext().getKey(), parent.toByteArray())));
|
||||
|
||||
splitGrpc.setParent(parent)
|
||||
.setParentHeader(grpcParentHeader)
|
||||
.setParentSignature(parentSig);
|
||||
|
||||
split.setParent(ObjectIdMapper.toModel(parent));
|
||||
}
|
||||
if (nonNull(split.getPrevious())) {
|
||||
splitGrpc.setPrevious(ObjectIdMapper.toGrpcMessage(split.getPrevious()));
|
||||
}
|
||||
grpcHeaderBuilder.setSplit(splitGrpc);
|
||||
grpcHeader = updateSplitValues(grpcHeader, split);
|
||||
}
|
||||
|
||||
var grpcHeader = grpcHeaderBuilder.build();
|
||||
var objectId = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build();
|
||||
var sig = frostfs.refs.Types.Signature.newBuilder()
|
||||
.setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte()))
|
||||
|
@ -92,14 +73,48 @@ public class ObjectToolsImpl extends ContextAccessor implements ToolsClient {
|
|||
.build();
|
||||
}
|
||||
|
||||
public Types.Header updateSplitValues(Types.Header grpcHeader, Split split) {
|
||||
if (isNull(split)) {
|
||||
return grpcHeader;
|
||||
}
|
||||
|
||||
var grpcSplit = grpcHeader.getSplit().toBuilder()
|
||||
.setSplitId(ByteString.copyFrom(split.getSplitId().toBinary()));
|
||||
|
||||
if (CollectionUtils.isNotEmpty(split.getChildren())) {
|
||||
var grpcChildren = split.getChildren().stream()
|
||||
.map(ObjectIdMapper::toGrpcMessage)
|
||||
.collect(Collectors.toList());
|
||||
grpcSplit.addAllChildren(grpcChildren);
|
||||
}
|
||||
|
||||
if (nonNull(split.getParentHeader())) {
|
||||
var grpcParentHeader = createHeader(split.getParentHeader(), new byte[]{});
|
||||
var parentObjectId = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcParentHeader)).build();
|
||||
var signature = frostfs.refs.Types.Signature.newBuilder()
|
||||
.setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte()))
|
||||
.setSign(ByteString.copyFrom(signData(getContext().getKey(), parentObjectId.toByteArray())))
|
||||
.build();
|
||||
|
||||
|
||||
grpcSplit
|
||||
.setParent(parentObjectId)
|
||||
.setParentHeader(grpcParentHeader)
|
||||
.setParentSignature(signature);
|
||||
|
||||
split.setParent(ObjectIdMapper.toModel(parentObjectId));
|
||||
}
|
||||
|
||||
grpcSplit.setPrevious(ObjectIdMapper.toGrpcMessage(split.getPrevious())).build();
|
||||
return grpcHeader.toBuilder().setSplit(grpcSplit.build()).build();
|
||||
}
|
||||
|
||||
private Types.Header createHeader(ObjectHeader header, byte[] payload) {
|
||||
var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header).toBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()));
|
||||
|
||||
if (header.getPayloadCheckSum() != null) {
|
||||
grpcHeader.setPayloadHash(sha256Checksum(header.getPayloadCheckSum()));
|
||||
} else if (payload != null) {
|
||||
if (payload != null) {
|
||||
grpcHeader.setPayloadHash(sha256Checksum(payload));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,14 @@ package info.frostfs.sdk.services.impl;
|
|||
import frostfs.session.Service;
|
||||
import frostfs.session.SessionServiceGrpc;
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.SessionToken;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.mappers.OwnerIdMapper;
|
||||
import info.frostfs.sdk.mappers.SessionMapper;
|
||||
import info.frostfs.sdk.mappers.object.OwnerIdMapper;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.services.SessionClient;
|
||||
import info.frostfs.sdk.tools.RequestConstructor;
|
||||
import info.frostfs.sdk.tools.Verifier;
|
||||
|
||||
import static info.frostfs.sdk.tools.RequestSigner.sign;
|
||||
|
||||
|
@ -25,7 +26,7 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
|
|||
public SessionToken createSession(long expiration) {
|
||||
var sessionToken = createSessionInternal(expiration);
|
||||
var token = SessionMapper.serialize(sessionToken);
|
||||
return new SessionToken(new byte[]{}, token);
|
||||
return new SessionToken(token);
|
||||
}
|
||||
|
||||
public Types.SessionToken createSessionInternal(long expiration) {
|
||||
|
@ -36,24 +37,26 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
|
|||
var request = Service.CreateRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addDefaultMetaHeader(request);
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return createSession(request.build());
|
||||
}
|
||||
|
||||
private Types.SessionToken createSession(Service.CreateRequest request) {
|
||||
var resp = serviceBlockingStub.create(request);
|
||||
var response = serviceBlockingStub.create(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
var lifetime = Types.SessionToken.Body.TokenLifetime.newBuilder()
|
||||
.setExp(request.getBody().getExpiration())
|
||||
.setIat(resp.getMetaHeader().getEpoch())
|
||||
.setNbf(resp.getMetaHeader().getEpoch())
|
||||
.setIat(response.getMetaHeader().getEpoch())
|
||||
.setNbf(response.getMetaHeader().getEpoch())
|
||||
.build();
|
||||
|
||||
var body = Types.SessionToken.Body.newBuilder()
|
||||
.setId(resp.getBody().getId())
|
||||
.setSessionKey(resp.getBody().getSessionKey())
|
||||
.setId(response.getBody().getId())
|
||||
.setSessionKey(response.getBody().getSessionKey())
|
||||
.setOwnerId(request.getBody().getOwnerId())
|
||||
.setLifetime(lifetime)
|
||||
.build();
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package info.frostfs.sdk.services.impl;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.services.SessionTools;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class SessionToolsImpl extends ContextAccessor implements SessionTools {
|
||||
|
||||
public SessionToolsImpl(ClientEnvironment clientEnvironment) {
|
||||
super(clientEnvironment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Types.SessionToken getOrCreateSession(SessionToken sessionToken, ClientEnvironment env) {
|
||||
if (isNull(sessionToken)) {
|
||||
return env.getFrostFSClient().createSessionInternal(-1);
|
||||
}
|
||||
|
||||
return SessionMapper.deserializeSessionToken(sessionToken.getToken());
|
||||
}
|
||||
|
||||
}
|
|
@ -2,17 +2,18 @@ package info.frostfs.sdk.services.impl.rwhelper;
|
|||
|
||||
import frostfs.object.Service;
|
||||
import frostfs.object.Types;
|
||||
import info.frostfs.sdk.dto.object.ObjectReader;
|
||||
import info.frostfs.sdk.tools.Verifier;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ObjectReader {
|
||||
public class ObjectReaderImpl implements ObjectReader {
|
||||
public static final String ERROR_UNEXPECTED_STREAM = "unexpected end of stream";
|
||||
public static final String ERROR_UNEXPECTED_MESSAGE_TYPE = "unexpected message type";
|
||||
|
||||
public Iterator<Service.GetResponse> call;
|
||||
|
||||
public ObjectReader(Iterator<Service.GetResponse> call) {
|
||||
public ObjectReaderImpl(Iterator<Service.GetResponse> call) {
|
||||
this.call = call;
|
||||
}
|
||||
|
|
@ -2,11 +2,13 @@ package info.frostfs.sdk.services.impl.rwhelper;
|
|||
|
||||
import frostfs.object.ObjectServiceGrpc;
|
||||
import frostfs.object.Service;
|
||||
import info.frostfs.sdk.utils.WaitUtil;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ObjectWriter {
|
||||
private static final long POLL_INTERVAL = 10;
|
||||
private final StreamObserver<Service.PutRequest> requestObserver;
|
||||
private final PutResponseCallback responseObserver;
|
||||
|
||||
|
@ -29,7 +31,7 @@ public class ObjectWriter {
|
|||
requestObserver.onCompleted();
|
||||
|
||||
while (isNull(responseObserver.getResponse())) {
|
||||
System.out.println("Waiting response");
|
||||
WaitUtil.sleep(POLL_INTERVAL);
|
||||
}
|
||||
|
||||
return responseObserver.getResponse();
|
||||
|
|
|
@ -3,6 +3,7 @@ package info.frostfs.sdk.tools;
|
|||
import io.grpc.Channel;
|
||||
import io.grpc.ChannelCredentials;
|
||||
import io.grpc.netty.NettyChannelBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -11,17 +12,23 @@ import static java.util.Objects.isNull;
|
|||
|
||||
public class GrpcClient {
|
||||
private static final String ERROR_INVALID_HOST_TEMPLATE = "Host %s has invalid format. Error: %s";
|
||||
private static final String ERROR_EMPTY_HOST_MESSAGE = "Host not provided";
|
||||
|
||||
private GrpcClient() {
|
||||
}
|
||||
|
||||
public static Channel initGrpcChannel(String host, ChannelCredentials creds) {
|
||||
public static Channel initGrpcChannel(String host, ChannelCredentials credentials) {
|
||||
if (StringUtils.isBlank(host)) {
|
||||
throw new IllegalArgumentException(ERROR_EMPTY_HOST_MESSAGE);
|
||||
}
|
||||
|
||||
try {
|
||||
URI uri = new URI(host);
|
||||
var channelBuilder = isNull(creds) ? NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort())
|
||||
: NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort(), creds);
|
||||
var channelBuilder = isNull(credentials)
|
||||
? NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()).usePlaintext()
|
||||
: NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort(), credentials);
|
||||
|
||||
return channelBuilder.usePlaintext().build();
|
||||
return channelBuilder.build();
|
||||
} catch (URISyntaxException exp) {
|
||||
throw new IllegalArgumentException(String.format(ERROR_INVALID_HOST_TEMPLATE, host, exp.getMessage()));
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package info.frostfs.sdk.tools;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import com.google.protobuf.MessageOrBuilder;
|
||||
|
||||
public class MessageHelper {
|
||||
|
||||
private MessageHelper() {
|
||||
}
|
||||
|
||||
public static Message getField(MessageOrBuilder messageOrBuilder, String fieldName) {
|
||||
return (Message) messageOrBuilder.getField(messageOrBuilder.getDescriptorForType().findFieldByName(fieldName));
|
||||
}
|
||||
|
||||
public static void setField(Message.Builder builder, String fieldName, Object value) {
|
||||
builder.setField(builder.getDescriptorForType().findFieldByName(fieldName), value);
|
||||
}
|
||||
}
|
|
@ -1,63 +1,130 @@
|
|||
package info.frostfs.sdk.tools;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.MetaHeader;
|
||||
import info.frostfs.sdk.dto.response.MetaHeader;
|
||||
import info.frostfs.sdk.jdo.ECDsa;
|
||||
import info.frostfs.sdk.mappers.MetaHeaderMapper;
|
||||
import info.frostfs.sdk.mappers.response.MetaHeaderMapper;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static info.frostfs.sdk.constants.FieldConst.META_HEADER_FIELD_NAME;
|
||||
import static info.frostfs.sdk.tools.MessageHelper.getField;
|
||||
import static info.frostfs.sdk.tools.MessageHelper.setField;
|
||||
import static info.frostfs.sdk.tools.RequestSigner.signMessagePart;
|
||||
import static info.frostfs.sdk.utils.MessageHelper.getField;
|
||||
import static info.frostfs.sdk.utils.MessageHelper.setField;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class RequestConstructor {
|
||||
private static final String ERROR_MESSAGE = "The message does not contain a field " + META_HEADER_FIELD_NAME;
|
||||
|
||||
private RequestConstructor() {
|
||||
}
|
||||
|
||||
public static void addDefaultMetaHeader(Message.Builder request) {
|
||||
addMetaHeader(request, null);
|
||||
public static void addMetaHeader(Message.Builder request) {
|
||||
addMetaHeader(request, null, null);
|
||||
}
|
||||
|
||||
public static void addMetaHeader(Message.Builder request, Types.RequestMetaHeader metaHeader) {
|
||||
public static void addMetaHeader(Message.Builder request, Map<String, String> xHeaders) {
|
||||
addMetaHeader(request, xHeaders, null);
|
||||
}
|
||||
|
||||
public static void addMetaHeader(Message.Builder request,
|
||||
Map<String, String> xHeaders,
|
||||
Types.SessionToken sessionToken) {
|
||||
if (isNull(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) {
|
||||
metaHeader = MetaHeaderMapper.toGrpcMessage(new MetaHeader());
|
||||
setField(request, META_HEADER_FIELD_NAME, metaHeader);
|
||||
}
|
||||
if (isNull(request.getDescriptorForType().findFieldByName(META_HEADER_FIELD_NAME))) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
public static void addObjectSessionToken(Message.Builder request,
|
||||
Types.SessionToken sessionToken,
|
||||
frostfs.refs.Types.ContainerID cid,
|
||||
frostfs.refs.Types.ObjectID oid,
|
||||
if (((Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME)).getSerializedSize() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var metaHeader = MetaHeaderMapper.toGrpcMessageBuilder(new MetaHeader());
|
||||
|
||||
if (nonNull(sessionToken) && sessionToken.getSerializedSize() > 0) {
|
||||
metaHeader.setSessionToken(sessionToken);
|
||||
}
|
||||
|
||||
if (MapUtils.isNotEmpty(xHeaders)) {
|
||||
var grpcXHeaders = xHeaders.entrySet()
|
||||
.stream()
|
||||
.map(e -> Types.XHeader.newBuilder().setKey(e.getKey()).setValue(e.getValue()).build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
metaHeader.addAllXHeaders(grpcXHeaders);
|
||||
}
|
||||
|
||||
setField(request, META_HEADER_FIELD_NAME, metaHeader.build());
|
||||
}
|
||||
|
||||
public static Types.SessionToken createObjectTokenContext(Types.SessionToken sessionToken,
|
||||
frostfs.refs.Types.Address address,
|
||||
Types.ObjectSessionContext.Verb verb,
|
||||
ECDsa key) {
|
||||
if (isNull(request) || isNull(sessionToken)) {
|
||||
return;
|
||||
if (isNull(sessionToken) || sessionToken.getBody().getObject().getTarget().getSerializedSize() > 0) {
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME);
|
||||
if (header.getSessionToken().getSerializedSize() > 0) {
|
||||
return;
|
||||
var target = Types.ObjectSessionContext.Target.newBuilder()
|
||||
.setContainer(address.getContainerId());
|
||||
|
||||
if (address.getObjectId().getSerializedSize() > 0) {
|
||||
target.addObjects(address.getObjectId());
|
||||
}
|
||||
|
||||
var ctx = Types.ObjectSessionContext.newBuilder()
|
||||
.setTarget(Types.ObjectSessionContext.Target.newBuilder().setContainer(cid).addObjects(oid).build())
|
||||
.setTarget(target.build())
|
||||
.setVerb(verb)
|
||||
.build();
|
||||
var body = sessionToken.getBody().toBuilder()
|
||||
.setObject(ctx)
|
||||
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()))
|
||||
.build();
|
||||
|
||||
var body = sessionToken.getBody().toBuilder().setObject(ctx).build();
|
||||
sessionToken = sessionToken.toBuilder()
|
||||
return sessionToken.toBuilder()
|
||||
.setSignature(signMessagePart(key, body))
|
||||
.setBody(body)
|
||||
.build();
|
||||
}
|
||||
|
||||
setField(request, META_HEADER_FIELD_NAME, header.toBuilder().setSessionToken(sessionToken).build());
|
||||
public static Types.SessionToken createContainerTokenContext(Types.SessionToken sessionToken,
|
||||
frostfs.refs.Types.ContainerID containerId,
|
||||
Types.ContainerSessionContext.Verb verb,
|
||||
frostfs.refs.Types.OwnerID ownerId,
|
||||
ECDsa key) {
|
||||
if (isNull(sessionToken) || sessionToken.getBody().getContainer().getContainerId().getSerializedSize() > 0) {
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
var containerSession = Types.ContainerSessionContext.newBuilder().setVerb(verb);
|
||||
|
||||
if (isNull(containerId) || containerId.getSerializedSize() == 0) {
|
||||
containerSession.setWildcard(true);
|
||||
} else {
|
||||
containerSession.setContainerId(containerId);
|
||||
}
|
||||
|
||||
var bodyBuilder = sessionToken.getBody().toBuilder()
|
||||
.setContainer(containerSession)
|
||||
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()));
|
||||
|
||||
if (nonNull(ownerId) && ownerId.getSerializedSize() > 0) {
|
||||
bodyBuilder.setOwnerId(ownerId);
|
||||
}
|
||||
|
||||
var body = bodyBuilder.build();
|
||||
|
||||
return sessionToken.toBuilder()
|
||||
.setSignature(signMessagePart(key, body))
|
||||
.setBody(body)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.google.protobuf.Message;
|
|||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.constants.CryptoConst;
|
||||
import info.frostfs.sdk.jdo.ECDsa;
|
||||
import info.frostfs.sdk.utils.MessageHelper;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
||||
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
|
||||
|
@ -92,10 +93,10 @@ public class RequestSigner {
|
|||
}
|
||||
|
||||
public static void sign(Message.Builder request, ECDsa key) {
|
||||
var meta = MessageHelper.getField(request, META_HEADER_FIELD_NAME);
|
||||
var body = MessageHelper.getField(request, BODY_FIELD_NAME);
|
||||
var verify = MessageHelper.getField(request, VERIFY_HEADER_FIELD_NAME);
|
||||
var verifyOrigin = MessageHelper.getField(verify, ORIGIN_FIELD_NAME);
|
||||
var meta = (Message) MessageHelper.getField(request, META_HEADER_FIELD_NAME);
|
||||
var body = (Message) MessageHelper.getField(request, BODY_FIELD_NAME);
|
||||
var verify = (Message) MessageHelper.getField(request, VERIFY_HEADER_FIELD_NAME);
|
||||
var verifyOrigin = (Message) MessageHelper.getField(verify, ORIGIN_FIELD_NAME);
|
||||
|
||||
Message.Builder verifyBuilder;
|
||||
if (verify instanceof Types.RequestVerificationHeader) {
|
||||
|
|
|
@ -3,7 +3,9 @@ package info.frostfs.sdk.tools;
|
|||
import com.google.protobuf.Message;
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.constants.CryptoConst;
|
||||
import info.frostfs.sdk.mappers.StatusMapper;
|
||||
import info.frostfs.sdk.exceptions.ResponseException;
|
||||
import info.frostfs.sdk.mappers.response.ResponseStatusMapper;
|
||||
import info.frostfs.sdk.utils.MessageHelper;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
||||
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
|
||||
|
@ -73,14 +75,14 @@ public class Verifier {
|
|||
}
|
||||
|
||||
var metaHeader = (Types.ResponseMetaHeader) MessageHelper.getField(response, META_HEADER_FIELD_NAME);
|
||||
var status = StatusMapper.toModel(metaHeader.getStatus());
|
||||
var status = ResponseStatusMapper.toModel(metaHeader.getStatus());
|
||||
if (!status.isSuccess()) {
|
||||
throw new IllegalArgumentException(status.toString());
|
||||
throw new ResponseException(status);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verify(Message response) {
|
||||
var body = MessageHelper.getField(response, BODY_FIELD_NAME);
|
||||
var body = (Message) MessageHelper.getField(response, BODY_FIELD_NAME);
|
||||
var metaHeader = (Types.ResponseMetaHeader) MessageHelper.getField(response, META_HEADER_FIELD_NAME);
|
||||
var verifyHeader = (Types.ResponseVerificationHeader)
|
||||
MessageHelper.getField(response, VERIFY_HEADER_FIELD_NAME);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package info.frostfs.sdk.utils;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import com.google.protobuf.MessageOrBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class MessageHelper {
|
||||
private static final String ERROR_MESSAGE = "One of the input parameters is null";
|
||||
|
||||
private MessageHelper() {
|
||||
}
|
||||
|
||||
public static Object getField(MessageOrBuilder messageOrBuilder, String fieldName) {
|
||||
if (isNull(messageOrBuilder) || StringUtils.isBlank(fieldName)) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
return messageOrBuilder.getField(messageOrBuilder.getDescriptorForType().findFieldByName(fieldName));
|
||||
}
|
||||
|
||||
public static void setField(Message.Builder builder, String fieldName, Object value) {
|
||||
if (isNull(builder) || StringUtils.isBlank(fieldName) || isNull(value)) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
builder.setField(builder.getDescriptorForType().findFieldByName(fieldName), value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package info.frostfs.sdk.utils;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.ValidationException;
|
||||
import javax.validation.Validator;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ValidatorUtils {
|
||||
private static final String OBJECT_IS_NULL = "object is null";
|
||||
private static final String ERROR_PROPERTY_TEMPLATE = "property %s with value %s %s";
|
||||
|
||||
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
|
||||
|
||||
public static <T> void validate(T object, Class<?>... classes) {
|
||||
if (isNull(object)) {
|
||||
throw new ValidationException(OBJECT_IS_NULL);
|
||||
}
|
||||
|
||||
Set<ConstraintViolation<T>> violations = validator.validate(object, classes);
|
||||
|
||||
if (CollectionUtils.isEmpty(violations)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] errors = (String[]) violations.stream()
|
||||
.map(violation -> String.format(
|
||||
ERROR_PROPERTY_TEMPLATE,
|
||||
violation.getPropertyPath().toString(),
|
||||
violation.getInvalidValue(),
|
||||
violation.getMessage()
|
||||
))
|
||||
.toArray();
|
||||
|
||||
throw new ValidationException(String.join(",", errors));
|
||||
}
|
||||
}
|
12
client/src/main/java/info/frostfs/sdk/utils/WaitUtil.java
Normal file
12
client/src/main/java/info/frostfs/sdk/utils/WaitUtil.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
package info.frostfs.sdk.utils;
|
||||
|
||||
public class WaitUtil {
|
||||
|
||||
public static void sleep(long ms) {
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,10 +13,10 @@ public class ArrayHelper {
|
|||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
byte[] result = new byte[startArray.length + endArray.length];
|
||||
byte[] joinedArray = new byte[startArray.length + endArray.length];
|
||||
|
||||
System.arraycopy(startArray, 0, result, 0, startArray.length);
|
||||
System.arraycopy(endArray, 0, result, startArray.length, endArray.length);
|
||||
return result;
|
||||
System.arraycopy(startArray, 0, joinedArray, 0, startArray.length);
|
||||
System.arraycopy(endArray, 0, joinedArray, startArray.length, endArray.length);
|
||||
return joinedArray;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package info.frostfs.sdk.constants;
|
||||
|
||||
public class FilterConst {
|
||||
|
||||
// HEADER_PREFIX is a prefix of key to object header value or property.
|
||||
public static final String HEADER_PREFIX = "$Object:";
|
||||
|
||||
// FILTER_HEADER_VERSION is a filter key to "version" field of the object header.
|
||||
public static final String FILTER_HEADER_VERSION = HEADER_PREFIX + "version";
|
||||
|
||||
// FILTER_HEADER_OBJECT_ID is a filter key to "object_id" field of the object.
|
||||
public static final String FILTER_HEADER_OBJECT_ID = HEADER_PREFIX + "objectID";
|
||||
|
||||
// FILTER_HEADER_CONTAINER_ID is a filter key to "container_id" field of the object header.
|
||||
public static final String FILTER_HEADER_CONTAINER_ID = HEADER_PREFIX + "containerID";
|
||||
|
||||
// FILTER_HEADER_OWNER_ID is a filter key to "owner_id" field of the object header.
|
||||
public static final String FILTER_HEADER_OWNER_ID = HEADER_PREFIX + "ownerID";
|
||||
|
||||
// FILTER_HEADER_CREATION_EPOCH is a filter key to "creation_epoch" field of the object header.
|
||||
public static final String FILTER_HEADER_CREATION_EPOCH = HEADER_PREFIX + "creationEpoch";
|
||||
|
||||
// FILTER_HEADER_PAYLOAD_LENGTH is a filter key to "payload_length" field of the object header.
|
||||
public static final String FILTER_HEADER_PAYLOAD_LENGTH = HEADER_PREFIX + "payloadLength";
|
||||
|
||||
// FILTER_HEADER_PAYLOAD_HASH is a filter key to "payload_hash" field of the object header.
|
||||
public static final String FILTER_HEADER_PAYLOAD_HASH = HEADER_PREFIX + "payloadHash";
|
||||
|
||||
// FILTER_HEADER_OBJECT_TYPE is a filter key to "object_type" field of the object header.
|
||||
public static final String FILTER_HEADER_OBJECT_TYPE = HEADER_PREFIX + "objectType";
|
||||
|
||||
// FILTER_HEADER_HOMOMORPHIC_HASH is a filter key to "homomorphic_hash" field of the object header.
|
||||
public static final String FILTER_HEADER_HOMOMORPHIC_HASH = HEADER_PREFIX + "homomorphicHash";
|
||||
|
||||
// FILTER_HEADER_PARENT is a filter key to "split.parent" field of the object header.
|
||||
public static final String FILTER_HEADER_PARENT = HEADER_PREFIX + "split.parent";
|
||||
|
||||
// FILTER_HEADER_SPLIT_ID is a filter key to "split.splitID" field of the object header.
|
||||
public static final String FILTER_HEADER_SPLIT_ID = HEADER_PREFIX + "split.splitID";
|
||||
|
||||
// FILTER_HEADER_EC_PARENT is a filter key to "ec.parent" field of the object header.
|
||||
public static final String FILTER_HEADER_EC_PARENT = HEADER_PREFIX + "ec.parent";
|
||||
|
||||
// FILTER_HEADER_ROOT is a filter key to check if regular object is on top of split hierarchy.
|
||||
public static final String FILTER_HEADER_ROOT = HEADER_PREFIX + "ROOT";
|
||||
|
||||
// FILTER_HEADER_PHY is a filter key to check if an object physically stored on a node.
|
||||
public static final String FILTER_HEADER_PHY = HEADER_PREFIX + "PHY";
|
||||
}
|
25
models/src/main/java/info/frostfs/sdk/dto/CheckSum.java
Normal file
25
models/src/main/java/info/frostfs/sdk/dto/CheckSum.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
|
||||
import info.frostfs.sdk.Helper;
|
||||
|
||||
public class CheckSum {
|
||||
// type is always Sha256
|
||||
public byte[] hash;
|
||||
|
||||
public CheckSum(byte[] content) {
|
||||
this.hash = Helper.getSha256(content);
|
||||
}
|
||||
|
||||
public byte[] getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(byte[] hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Helper.getHexString(hash);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
|
||||
public class SessionToken {
|
||||
private final byte[] id;
|
||||
private final byte[] sessionKey;
|
||||
|
||||
public SessionToken(byte[] id, byte[] sessionKey) {
|
||||
this.id = id;
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public byte[] getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte[] getSessionKey() {
|
||||
return sessionKey;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package info.frostfs.sdk.dto.container;
|
||||
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.dto.netmap.PlacementPolicy;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.enums.BasicAcl;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.frostfs.sdk.dto.netmap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class NetmapSnapshot {
|
||||
|
@ -8,7 +9,7 @@ public class NetmapSnapshot {
|
|||
|
||||
public NetmapSnapshot(Long epoch, List<NodeInfo> nodeInfoCollection) {
|
||||
this.epoch = epoch;
|
||||
this.nodeInfoCollection = nodeInfoCollection;
|
||||
this.nodeInfoCollection = Collections.unmodifiableList(nodeInfoCollection);
|
||||
}
|
||||
|
||||
public Long getEpoch() {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package info.frostfs.sdk.dto.netmap;
|
||||
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.enums.NodeState;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -17,8 +17,8 @@ public class NodeInfo {
|
|||
Map<String, String> attributes, byte[] publicKey) {
|
||||
this.state = state;
|
||||
this.version = version;
|
||||
this.addresses = addresses;
|
||||
this.attributes = attributes;
|
||||
this.addresses = Collections.unmodifiableList(addresses);
|
||||
this.attributes = Collections.unmodifiableMap(attributes);
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.netmap;
|
||||
|
||||
import static info.frostfs.sdk.constants.AppConst.DEFAULT_MAJOR_VERSION;
|
||||
import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION;
|
|
@ -1,7 +1,5 @@
|
|||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import info.frostfs.sdk.dto.Split;
|
||||
import info.frostfs.sdk.dto.SplitId;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
|
@ -9,10 +7,10 @@ import java.util.List;
|
|||
|
||||
public class LinkObject extends ObjectFrostFS {
|
||||
|
||||
public LinkObject(ContainerId cid, SplitId splitId, LargeObject largeObject) {
|
||||
public LinkObject(ContainerId cid, SplitId splitId, ObjectHeader largeObjectHeader) {
|
||||
super(cid, new byte[]{});
|
||||
var split = new Split(splitId);
|
||||
split.setParentHeader(largeObject.getHeader());
|
||||
split.setParentHeader(largeObjectHeader);
|
||||
this.getHeader().setSplit(split);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +1,24 @@
|
|||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import info.frostfs.sdk.dto.OwnerId;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.constants.FieldConst;
|
||||
import info.frostfs.sdk.constants.FilterConst;
|
||||
import info.frostfs.sdk.dto.CheckSum;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.enums.ObjectMatchType;
|
||||
|
||||
public class ObjectFilter {
|
||||
private static final String HEADER_PREFIX = "$Object:";
|
||||
|
||||
public abstract class ObjectFilter<T> {
|
||||
private ObjectMatchType matchType;
|
||||
private String key;
|
||||
private String value;
|
||||
private T value;
|
||||
|
||||
|
||||
public ObjectFilter(ObjectMatchType matchType, String key, String value) {
|
||||
public ObjectFilter(ObjectMatchType matchType, String key, T value) {
|
||||
this.matchType = matchType;
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ObjectFilter ObjectIdFilter(ObjectMatchType matchType, ObjectId objectId) {
|
||||
return new ObjectFilter(matchType, HEADER_PREFIX + "objectID", objectId.getValue());
|
||||
}
|
||||
|
||||
public static ObjectFilter OwnerFilter(ObjectMatchType matchType, OwnerId ownerId) {
|
||||
return new ObjectFilter(matchType, HEADER_PREFIX + "ownerID", ownerId.getValue());
|
||||
}
|
||||
|
||||
public static ObjectFilter RootFilter() {
|
||||
return new ObjectFilter(ObjectMatchType.UNSPECIFIED, HEADER_PREFIX + "ROOT", "");
|
||||
}
|
||||
|
||||
public static ObjectFilter VersionFilter(ObjectMatchType matchType, Version version) {
|
||||
return new ObjectFilter(matchType, HEADER_PREFIX + "version", version.toString());
|
||||
}
|
||||
|
||||
public ObjectMatchType getMatchType() {
|
||||
return matchType;
|
||||
}
|
||||
|
@ -50,11 +35,94 @@ public class ObjectFilter {
|
|||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
public void setValue(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getSerializedValue() {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
public static class FilterByAttribute extends ObjectFilter<String> {
|
||||
public FilterByAttribute(ObjectMatchType matchType, String key, String value) {
|
||||
super(matchType, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByObjectId extends ObjectFilter<ObjectId> {
|
||||
public FilterByObjectId(ObjectMatchType matchType, ObjectId value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_OBJECT_ID, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByOwnerId extends ObjectFilter<OwnerId> {
|
||||
public FilterByOwnerId(ObjectMatchType matchType, OwnerId value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_OWNER_ID, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByVersion extends ObjectFilter<Version> {
|
||||
public FilterByVersion(ObjectMatchType matchType, Version value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_VERSION, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByContainerId extends ObjectFilter<ContainerId> {
|
||||
public FilterByContainerId(ObjectMatchType matchType, ContainerId value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_CONTAINER_ID, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByEpoch extends ObjectFilter<Long> {
|
||||
public FilterByEpoch(ObjectMatchType matchType, long value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_CREATION_EPOCH, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByPayloadLength extends ObjectFilter<Long> {
|
||||
public FilterByPayloadLength(ObjectMatchType matchType, long value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_PAYLOAD_LENGTH, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByPayloadHash extends ObjectFilter<CheckSum> {
|
||||
public FilterByPayloadHash(ObjectMatchType matchType, CheckSum value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_PAYLOAD_HASH, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByParent extends ObjectFilter<ObjectId> {
|
||||
public FilterByParent(ObjectMatchType matchType, ObjectId value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_PARENT, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterBySplitId extends ObjectFilter<SplitId> {
|
||||
public FilterBySplitId(ObjectMatchType matchType, SplitId value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_SPLIT_ID, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class FilterByECParent extends ObjectFilter<ObjectId> {
|
||||
public FilterByECParent(ObjectMatchType matchType, ObjectId value) {
|
||||
super(matchType, FilterConst.FILTER_HEADER_EC_PARENT, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByRootObject extends ObjectFilter<String> {
|
||||
public FilterByRootObject() {
|
||||
super(ObjectMatchType.UNSPECIFIED, FilterConst.FILTER_HEADER_ROOT, FieldConst.EMPTY_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilterByPhysicallyStored extends ObjectFilter<String> {
|
||||
public FilterByPhysicallyStored() {
|
||||
super(ObjectMatchType.UNSPECIFIED, FilterConst.FILTER_HEADER_PHY, FieldConst.EMPTY_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import info.frostfs.sdk.dto.Split;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
@ -13,6 +11,7 @@ public class ObjectFrostFS {
|
|||
private final ObjectHeader header;
|
||||
private ObjectId objectId;
|
||||
private byte[] payload;
|
||||
private ObjectReader objectReader;
|
||||
|
||||
public ObjectFrostFS(ObjectHeader header, ObjectId objectId, byte[] payload) {
|
||||
if (isNull(header)) {
|
||||
|
@ -26,12 +25,20 @@ public class ObjectFrostFS {
|
|||
|
||||
public ObjectFrostFS(ContainerId containerId, byte[] payload) {
|
||||
this.payload = payload;
|
||||
this.header = new ObjectHeader(containerId, new ArrayList<>());
|
||||
this.header = new ObjectHeader(containerId);
|
||||
}
|
||||
|
||||
public ObjectFrostFS(ContainerId containerId, byte[] payload, ObjectType objectType) {
|
||||
this.payload = payload;
|
||||
this.header = new ObjectHeader(containerId, objectType, new ArrayList<>());
|
||||
this.header = new ObjectHeader(containerId, objectType);
|
||||
}
|
||||
|
||||
public ObjectReader getObjectReader() {
|
||||
return objectReader;
|
||||
}
|
||||
|
||||
public void setObjectReader(ObjectReader objectReader) {
|
||||
this.objectReader = objectReader;
|
||||
}
|
||||
|
||||
public ObjectHeader getHeader() {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import info.frostfs.sdk.dto.OwnerId;
|
||||
import info.frostfs.sdk.dto.Split;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
|
@ -33,24 +33,18 @@ public class ObjectHeader {
|
|||
this.version = version;
|
||||
}
|
||||
|
||||
public ObjectHeader(ContainerId containerId, ObjectType objectType, List<ObjectAttribute> attributes) {
|
||||
if (isNull(containerId) || isNull(objectType)) {
|
||||
throw new IllegalArgumentException("ContainerId or objectType is not present");
|
||||
public ObjectHeader(ContainerId containerId, ObjectType objectType, ObjectAttribute... attributes) {
|
||||
this(
|
||||
containerId,
|
||||
objectType,
|
||||
Arrays.stream(attributes).collect(Collectors.toList()),
|
||||
0L,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
this.attributes = attributes;
|
||||
this.containerId = containerId;
|
||||
this.objectType = objectType;
|
||||
}
|
||||
|
||||
public ObjectHeader(ContainerId containerId, List<ObjectAttribute> attributes) {
|
||||
if (isNull(containerId)) {
|
||||
throw new IllegalArgumentException("ContainerId is not present");
|
||||
}
|
||||
|
||||
this.attributes = attributes;
|
||||
this.containerId = containerId;
|
||||
this.objectType = ObjectType.REGULAR;
|
||||
public ObjectHeader(ContainerId containerId, ObjectAttribute... attributes) {
|
||||
this(containerId, ObjectType.REGULAR, attributes);
|
||||
}
|
||||
|
||||
public OwnerId getOwnerId() {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
public interface ObjectReader {
|
||||
byte[] readChunk();
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import info.frostfs.sdk.Base58;
|
||||
|
||||
|
@ -27,4 +27,9 @@ public class OwnerId {
|
|||
public byte[] toHash() {
|
||||
return Base58.decode(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.response.Signature;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -15,6 +15,7 @@ public class Split {
|
|||
private ObjectId previous;
|
||||
private Signature parentSignature;
|
||||
private ObjectHeader parentHeader;
|
||||
private Types.Signature parentSignatureGrpc;
|
||||
|
||||
public Split() {
|
||||
this(new SplitId());
|
||||
|
@ -68,4 +69,12 @@ public class Split {
|
|||
public List<ObjectId> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public Types.Signature getParentSignatureGrpc() {
|
||||
return parentSignatureGrpc;
|
||||
}
|
||||
|
||||
public void setParentSignatureGrpc(Types.Signature parentSignatureGrpc) {
|
||||
this.parentSignatureGrpc = parentSignatureGrpc;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -21,8 +21,8 @@ public class SplitId {
|
|||
this.id = asUuid(binary);
|
||||
}
|
||||
|
||||
public SplitId(String str) {
|
||||
this.id = UUID.fromString(str);
|
||||
public SplitId(String string) {
|
||||
this.id = UUID.fromString(string);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,4 +1,6 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.response;
|
||||
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
|
||||
import static info.frostfs.sdk.constants.AppConst.DEFAULT_MAJOR_VERSION;
|
||||
import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION;
|
|
@ -1,20 +1,20 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.response;
|
||||
|
||||
import info.frostfs.sdk.enums.StatusCode;
|
||||
|
||||
import static info.frostfs.sdk.constants.FieldConst.EMPTY_STRING;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class Status {
|
||||
public class ResponseStatus {
|
||||
private StatusCode code;
|
||||
private String message;
|
||||
|
||||
public Status(StatusCode code, String message) {
|
||||
public ResponseStatus(StatusCode code, String message) {
|
||||
this.code = code;
|
||||
this.message = isNull(message) ? EMPTY_STRING : message;
|
||||
}
|
||||
|
||||
public Status(StatusCode code) {
|
||||
public ResponseStatus(StatusCode code) {
|
||||
this.code = code;
|
||||
this.message = EMPTY_STRING;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.dto;
|
||||
package info.frostfs.sdk.dto.response;
|
||||
|
||||
import info.frostfs.sdk.enums.SignatureScheme;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package info.frostfs.sdk.dto.session;
|
||||
|
||||
public class SessionToken {
|
||||
private final byte[] token;
|
||||
|
||||
public SessionToken(byte[] token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public byte[] getToken() {
|
||||
return token;
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.MetaHeader;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class MetaHeaderMapper {
|
||||
|
||||
private MetaHeaderMapper() {
|
||||
}
|
||||
|
||||
public static Types.RequestMetaHeader toGrpcMessage(MetaHeader metaHeader) {
|
||||
if (isNull(metaHeader)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Types.RequestMetaHeader.newBuilder()
|
||||
.setVersion(VersionMapper.toGrpcMessage(metaHeader.getVersion()))
|
||||
.setEpoch(metaHeader.getEpoch())
|
||||
.setTtl(metaHeader.getTtl())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -4,8 +4,8 @@ import com.google.protobuf.ByteString;
|
|||
import frostfs.container.Types;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.enums.BasicAcl;
|
||||
import info.frostfs.sdk.mappers.VersionMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.PlacementPolicyMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.VersionMapper;
|
||||
|
||||
import static info.frostfs.sdk.UuidExtension.asBytes;
|
||||
import static info.frostfs.sdk.UuidExtension.asUuid;
|
||||
|
|
|
@ -5,7 +5,6 @@ import frostfs.netmap.Types;
|
|||
import frostfs.netmap.Types.NodeInfo.Attribute;
|
||||
import info.frostfs.sdk.dto.netmap.NodeInfo;
|
||||
import info.frostfs.sdk.enums.NodeState;
|
||||
import info.frostfs.sdk.mappers.VersionMapper;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.netmap;
|
||||
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
|
@ -12,7 +12,7 @@ public class ObjectFilterMapper {
|
|||
private ObjectFilterMapper() {
|
||||
}
|
||||
|
||||
public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter filter) {
|
||||
public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter<?> filter) {
|
||||
if (isNull(filter)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class ObjectFilterMapper {
|
|||
return Service.SearchRequest.Body.Filter.newBuilder()
|
||||
.setMatchType(objectMatchType)
|
||||
.setKey(filter.getKey())
|
||||
.setValue(filter.getValue())
|
||||
.setValue(filter.getSerializedValue())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,30 @@
|
|||
package info.frostfs.sdk.mappers.object;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import frostfs.object.Types;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectAttribute;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
import info.frostfs.sdk.mappers.VersionMapper;
|
||||
import info.frostfs.sdk.mappers.container.ContainerIdMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.VersionMapper;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class ObjectHeaderMapper {
|
||||
private static final String ERROR_UNKNOWN_VALUE_TEMPLATE = "Unknown ObjectType. Value: %s.";
|
||||
private static final String ERROR_OBJECT_HEADER_MISSING_ERROR = "ObjectHeader is not present";
|
||||
|
||||
private ObjectHeaderMapper() {
|
||||
}
|
||||
|
||||
public static Types.Header toGrpcMessage(ObjectHeader header) {
|
||||
if (isNull(header)) {
|
||||
return null;
|
||||
throw new IllegalArgumentException(ERROR_OBJECT_HEADER_MISSING_ERROR);
|
||||
}
|
||||
|
||||
var objectType = Types.ObjectType.forNumber(header.getObjectType().value);
|
||||
|
@ -32,13 +35,23 @@ public class ObjectHeaderMapper {
|
|||
}
|
||||
|
||||
var head = Types.Header.newBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(header.getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(header.getVersion()))
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(header.getContainerId()))
|
||||
.setObjectType(objectType);
|
||||
.setObjectType(objectType)
|
||||
.setPayloadLength(header.getPayloadLength());
|
||||
|
||||
for (ObjectAttribute objectAttribute : header.getAttributes()) {
|
||||
head.addAttributes(ObjectAttributeMapper.toGrpcMessage(objectAttribute));
|
||||
}
|
||||
|
||||
if (nonNull(header.getSplit())) {
|
||||
var grpcSplit = Types.Header.Split.newBuilder()
|
||||
.setSplitId(ByteString.copyFrom(header.getSplit().getSplitId().toBinary()))
|
||||
.build();
|
||||
head.setSplit(grpcSplit);
|
||||
}
|
||||
|
||||
return head.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.object;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.OwnerId;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package info.frostfs.sdk.mappers.response;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.response.MetaHeader;
|
||||
import info.frostfs.sdk.mappers.netmap.VersionMapper;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class MetaHeaderMapper {
|
||||
private static final String ERROR_META_HEADER_MISSING_ERROR = "MetaHeader is not present";
|
||||
|
||||
private MetaHeaderMapper() {
|
||||
}
|
||||
|
||||
public static Types.RequestMetaHeader toGrpcMessage(MetaHeader metaHeader) {
|
||||
if (isNull(metaHeader)) {
|
||||
throw new IllegalArgumentException(ERROR_META_HEADER_MISSING_ERROR);
|
||||
}
|
||||
|
||||
return toGrpcMessageBuilder(metaHeader).build();
|
||||
}
|
||||
|
||||
public static Types.RequestMetaHeader.Builder toGrpcMessageBuilder(MetaHeader metaHeader) {
|
||||
if (isNull(metaHeader)) {
|
||||
throw new IllegalArgumentException(ERROR_META_HEADER_MISSING_ERROR);
|
||||
}
|
||||
|
||||
return Types.RequestMetaHeader.newBuilder()
|
||||
.setVersion(VersionMapper.toGrpcMessage(metaHeader.getVersion()))
|
||||
.setEpoch(metaHeader.getEpoch())
|
||||
.setTtl(metaHeader.getTtl());
|
||||
}
|
||||
}
|
|
@ -1,20 +1,20 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.response;
|
||||
|
||||
import frostfs.status.Types;
|
||||
import info.frostfs.sdk.dto.Status;
|
||||
import info.frostfs.sdk.dto.response.ResponseStatus;
|
||||
import info.frostfs.sdk.enums.StatusCode;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class StatusMapper {
|
||||
public class ResponseStatusMapper {
|
||||
private static final String ERROR_UNKNOWN_VALUE_TEMPLATE = "Unknown StatusCode. Value: %s.";
|
||||
|
||||
private StatusMapper() {
|
||||
private ResponseStatusMapper() {
|
||||
}
|
||||
|
||||
public static Status toModel(Types.Status status) {
|
||||
public static ResponseStatus toModel(Types.Status status) {
|
||||
if (isNull(status)) {
|
||||
return new Status(StatusCode.SUCCESS);
|
||||
return new ResponseStatus(StatusCode.SUCCESS);
|
||||
}
|
||||
|
||||
var statusCode = StatusCode.get(status.getCode());
|
||||
|
@ -24,6 +24,6 @@ public class StatusMapper {
|
|||
);
|
||||
}
|
||||
|
||||
return new Status(statusCode, status.getMessage());
|
||||
return new ResponseStatus(statusCode, status.getMessage());
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.response;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.Signature;
|
||||
import info.frostfs.sdk.dto.response.Signature;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.session;
|
||||
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
@ -1,33 +0,0 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
|
||||
import info.frostfs.sdk.dto.MetaHeader;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class MetaHeaderMapperTest {
|
||||
|
||||
@Test
|
||||
void toGrpcMessage_success() {
|
||||
//Given
|
||||
var version = new Version(1, 2);
|
||||
var metaHeader = new MetaHeader(version, 1, 2);
|
||||
|
||||
//When
|
||||
var result = MetaHeaderMapper.toGrpcMessage(metaHeader);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
assertEquals(metaHeader.getEpoch(), result.getEpoch());
|
||||
assertEquals(metaHeader.getTtl(), result.getTtl());
|
||||
assertEquals(metaHeader.getVersion().getMajor(), result.getVersion().getMajor());
|
||||
assertEquals(metaHeader.getVersion().getMinor(), result.getVersion().getMinor());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toGrpcMessage_null() {
|
||||
//When + Then
|
||||
assertNull(MetaHeaderMapper.toGrpcMessage(null));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.netmap;
|
||||
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.Version;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
|
@ -18,7 +18,7 @@ public class ObjectFilterMapperTest {
|
|||
@EnumSource(value = ObjectMatchType.class)
|
||||
void toGrpcMessage_success(ObjectMatchType type) {
|
||||
//Given
|
||||
var objectFilter = new ObjectFilter(type, "key", "value");
|
||||
var objectFilter = new ObjectFilter.FilterByAttribute(type, "key", "value");
|
||||
|
||||
//When
|
||||
var result = ObjectFilterMapper.toGrpcMessage(objectFilter);
|
||||
|
@ -40,7 +40,7 @@ public class ObjectFilterMapperTest {
|
|||
@Test
|
||||
void toGrpcMessage_notValidScheme() {
|
||||
//Given
|
||||
var objectFilter = new ObjectFilter(UNSPECIFIED, "key", "value");
|
||||
var objectFilter = new ObjectFilter.FilterByAttribute(UNSPECIFIED, "key", "value");
|
||||
|
||||
//When + Then
|
||||
try (MockedStatic<Types.MatchType> mockStatic = mockStatic(Types.MatchType.class)) {
|
||||
|
|
|
@ -3,16 +3,16 @@ package info.frostfs.sdk.mappers.object;
|
|||
import com.google.protobuf.ByteString;
|
||||
import frostfs.object.Types;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.dto.object.ObjectAttribute;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
|
@ -27,8 +27,11 @@ public class ObjectHeaderMapperTest {
|
|||
var objectHeader = new ObjectHeader(
|
||||
containerId,
|
||||
type,
|
||||
List.of(new ObjectAttribute("Filename", "cat.jpg"), new ObjectAttribute("Filename2", "cat2.jpg"))
|
||||
new ObjectAttribute("Filename", "cat.jpg"),
|
||||
new ObjectAttribute("Filename2", "cat2.jpg")
|
||||
);
|
||||
objectHeader.setOwnerId(new OwnerId("NVxUSpEEJzYXZZtUs18PrJTD9QZkLLNQ8S"));
|
||||
objectHeader.setVersion(new Version(1, 2));
|
||||
|
||||
//When
|
||||
var result = ObjectHeaderMapper.toGrpcMessage(objectHeader);
|
||||
|
@ -59,7 +62,7 @@ public class ObjectHeaderMapperTest {
|
|||
void toGrpcMessage_notValidScheme() {
|
||||
//Given
|
||||
var containerId = new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R");
|
||||
var objectHeader = new ObjectHeader(containerId, ObjectType.REGULAR, null);
|
||||
var objectHeader = new ObjectHeader(containerId, ObjectType.REGULAR);
|
||||
|
||||
//When + Then
|
||||
try (MockedStatic<Types.ObjectType> mockStatic = mockStatic(Types.ObjectType.class)) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.object;
|
||||
|
||||
import info.frostfs.sdk.dto.OwnerId;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
@ -0,0 +1,57 @@
|
|||
package info.frostfs.sdk.mappers.response;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.dto.response.MetaHeader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class MetaHeaderMapperTest {
|
||||
|
||||
@Test
|
||||
void toGrpcMessage_success() {
|
||||
//Given
|
||||
var version = new Version(1, 2);
|
||||
var metaHeader = new MetaHeader(version, 1, 2);
|
||||
|
||||
//When
|
||||
Types.RequestMetaHeader result = MetaHeaderMapper.toGrpcMessage(metaHeader);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
assertEquals(metaHeader.getEpoch(), result.getEpoch());
|
||||
assertEquals(metaHeader.getTtl(), result.getTtl());
|
||||
assertEquals(metaHeader.getVersion().getMajor(), result.getVersion().getMajor());
|
||||
assertEquals(metaHeader.getVersion().getMinor(), result.getVersion().getMinor());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toGrpcMessage_null() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> MetaHeaderMapper.toGrpcMessage(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toGrpcMessageBuilder_success() {
|
||||
//Given
|
||||
var version = new Version(1, 2);
|
||||
var metaHeader = new MetaHeader(version, 1, 2);
|
||||
|
||||
//When
|
||||
Types.RequestMetaHeader.Builder result = MetaHeaderMapper.toGrpcMessageBuilder(metaHeader);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
assertEquals(metaHeader.getEpoch(), result.getEpoch());
|
||||
assertEquals(metaHeader.getTtl(), result.getTtl());
|
||||
assertEquals(metaHeader.getVersion().getMajor(), result.getVersion().getMajor());
|
||||
assertEquals(metaHeader.getVersion().getMinor(), result.getVersion().getMinor());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toGrpcMessageBuilder_null() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> MetaHeaderMapper.toGrpcMessageBuilder(null));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.response;
|
||||
|
||||
import frostfs.status.Types;
|
||||
import info.frostfs.sdk.enums.StatusCode;
|
||||
|
@ -8,7 +8,7 @@ import org.junit.jupiter.params.provider.EnumSource;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class StatusMapperTest {
|
||||
public class ResponseStatusMapperTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(value = StatusCode.class)
|
||||
|
@ -20,7 +20,7 @@ public class StatusMapperTest {
|
|||
.build();
|
||||
|
||||
//When
|
||||
var result = StatusMapper.toModel(status);
|
||||
var result = ResponseStatusMapper.toModel(status);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
|
@ -31,7 +31,7 @@ public class StatusMapperTest {
|
|||
@Test
|
||||
void toModel_null() {
|
||||
//When
|
||||
var result = StatusMapper.toModel(null);
|
||||
var result = ResponseStatusMapper.toModel(null);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
|
@ -48,6 +48,6 @@ public class StatusMapperTest {
|
|||
.build();
|
||||
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> StatusMapper.toModel(status));
|
||||
assertThrows(IllegalArgumentException.class, () -> ResponseStatusMapper.toModel(status));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.response;
|
||||
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.Signature;
|
||||
import info.frostfs.sdk.dto.response.Signature;
|
||||
import info.frostfs.sdk.enums.SignatureScheme;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.mappers;
|
||||
package info.frostfs.sdk.mappers.session;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import frostfs.session.Types;
|
Loading…
Reference in a new issue