[#12] Extend methods logic #13

Merged
orikik merged 2 commits from orikik/frostfs-sdk-java:feature/func-extension into master 2024-11-02 14:21:57 +00:00
69 changed files with 1335 additions and 588 deletions

View file

@ -1,16 +1,16 @@
package info.frostfs.sdk; package info.frostfs.sdk;
import frostfs.session.Types; 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.Container;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.dto.netmap.NetmapSnapshot; import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
import info.frostfs.sdk.dto.netmap.NodeInfo; 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.ObjectFilter;
import info.frostfs.sdk.dto.object.ObjectFrostFS; import info.frostfs.sdk.dto.object.ObjectFrostFS;
import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.dto.object.ObjectId; 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.ClientEnvironment;
import info.frostfs.sdk.jdo.ClientSettings; import info.frostfs.sdk.jdo.ClientSettings;
import info.frostfs.sdk.jdo.NetworkSettings; import info.frostfs.sdk.jdo.NetworkSettings;
@ -23,6 +23,7 @@ import java.util.List;
import static info.frostfs.sdk.tools.GrpcClient.initGrpcChannel; import static info.frostfs.sdk.tools.GrpcClient.initGrpcChannel;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient { public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient {
private static final String ERROR_CLIENT_OPTIONS_INIT = "Options must be initialized."; 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); throw new IllegalArgumentException(ERROR_CLIENT_OPTIONS_INIT);
} }
clientSettings.validate(); Channel channel = nonNull(clientSettings.getChannel()) ? clientSettings.getChannel()
: initGrpcChannel(clientSettings.getHost(), clientSettings.getCredentials());
Channel channel = initGrpcChannel(clientSettings.getHost(), clientSettings.getCreds());
ClientEnvironment clientEnvironment = ClientEnvironment clientEnvironment =
new ClientEnvironment(clientSettings.getKey(), channel, new Version(), this); new ClientEnvironment(clientSettings.getKey(), channel, new Version(), this);
@ -98,13 +98,18 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien
return objectClientImpl.putObject(parameters); return objectClientImpl.putObject(parameters);
} }
@Override
public ObjectId putSingleObject(ObjectFrostFS objectFrostFS) {
return objectClientImpl.putSingleObject(objectFrostFS);
}
@Override @Override
public void deleteObject(ContainerId containerId, ObjectId objectId) { public void deleteObject(ContainerId containerId, ObjectId objectId) {
objectClientImpl.deleteObject(containerId, objectId); objectClientImpl.deleteObject(containerId, objectId);
} }
@Override @Override
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters) { public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) {
return objectClientImpl.searchObjects(cid, filters); return objectClientImpl.searchObjects(cid, filters);
} }

View file

@ -0,0 +1,6 @@
package info.frostfs.sdk.enums;
public enum WaitExpects {
EXISTS,
REMOVED
}

View file

@ -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;
}
}

View file

@ -0,0 +1,6 @@
package info.frostfs.sdk.exceptions;
public class TimeoutException extends RuntimeException {
public TimeoutException() {
}
}

View file

@ -1,14 +1,16 @@
package info.frostfs.sdk.jdo; package info.frostfs.sdk.jdo;
import info.frostfs.sdk.FrostFSClient; import info.frostfs.sdk.FrostFSClient;
import info.frostfs.sdk.dto.OwnerId; import info.frostfs.sdk.dto.netmap.Version;
import info.frostfs.sdk.dto.Version; import info.frostfs.sdk.dto.object.OwnerId;
import io.grpc.Channel; import io.grpc.Channel;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
public class ClientEnvironment { public class ClientEnvironment {
private static final String ERROR_MESSAGE = "One of the input attributes is missing";
private final OwnerId ownerId; private final OwnerId ownerId;
private final Version version; private final Version version;
private final ECDsa key; private final ECDsa key;
@ -18,7 +20,7 @@ public class ClientEnvironment {
public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient) { public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient) {
if (StringUtils.isEmpty(wif) || isNull(channel) || isNull(version) || isNull(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); this.key = new ECDsa(wif);

View file

@ -1,14 +1,20 @@
package info.frostfs.sdk.jdo; package info.frostfs.sdk.jdo;
import io.grpc.Channel;
import io.grpc.ChannelCredentials; import io.grpc.ChannelCredentials;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public class ClientSettings { import static java.util.Objects.isNull;
private static final String ERROR_TEMPLATE = "%s is required parameter.";
public String key; public class ClientSettings {
public String host; private static final String ERROR_TEMPLATE = "%s required parameter.";
public ChannelCredentials creds; 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) { public ClientSettings(String key, String host) {
this.key = key; this.key = key;
@ -16,46 +22,44 @@ public class ClientSettings {
validate(); validate();
} }
public ClientSettings(String key, String host, ChannelCredentials creds) { public ClientSettings(String key, String host, ChannelCredentials credentials) {
this.key = key; this.key = key;
this.host = host; this.host = host;
this.creds = creds; this.credentials = credentials;
validate(); validate();
} }
public ChannelCredentials getCreds() { public ClientSettings(String key, Channel channel) {
return creds; this.key = key;
this.channel = channel;
validate();
} }
public void setCreds(ChannelCredentials creds) { public Channel getChannel() {
this.creds = creds; return channel;
}
public ChannelCredentials getCredentials() {
return credentials;
} }
public String getHost() { public String getHost() {
return host; return host;
} }
public void setHost(String host) {
this.host = host;
}
public String getKey() { public String getKey() {
return key; return key;
} }
public void setKey(String key) {
this.key = key;
}
public void validate() { public void validate() {
StringBuilder errorMessage = new StringBuilder(); StringBuilder errorMessage = new StringBuilder();
if (StringUtils.isEmpty(key)) { 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)) { if (StringUtils.isEmpty(host) && isNull(channel)) {
errorMessage.append(String.format(ERROR_TEMPLATE, "Host")).append(System.lineSeparator()); errorMessage.append(String.format(ERROR_TEMPLATE, HOST_AND_CHANNEL_NAME)).append(System.lineSeparator());
} }
if (errorMessage.length() != 0) { if (errorMessage.length() != 0) {

View file

@ -7,13 +7,15 @@ import java.security.PrivateKey;
import static info.frostfs.sdk.KeyExtension.*; import static info.frostfs.sdk.KeyExtension.*;
public class ECDsa { public class ECDsa {
private static final String ERROR_MESSAGE = "WIF is invalid";
private final byte[] publicKeyByte; private final byte[] publicKeyByte;
private final byte[] privateKeyByte; private final byte[] privateKeyByte;
private final PrivateKey privateKey; private final PrivateKey privateKey;
public ECDsa(String wif) { public ECDsa(String wif) {
if (StringUtils.isEmpty(wif)) { if (StringUtils.isEmpty(wif)) {
throw new IllegalArgumentException("Wif is invalid"); throw new IllegalArgumentException(ERROR_MESSAGE);
} }
this.privateKeyByte = getPrivateKeyFromWIF(wif); this.privateKeyByte = getPrivateKeyFromWIF(wif);

View file

@ -5,21 +5,21 @@ import java.util.Map;
public class NetworkSettings { public class NetworkSettings {
public Long auditFee; private Long auditFee;
public Long basicIncomeRate; private Long basicIncomeRate;
public Long containerFee; private Long containerFee;
public Long containerAliasFee; private Long containerAliasFee;
public Long innerRingCandidateFee; private Long innerRingCandidateFee;
public Long withdrawFee; private Long withdrawFee;
public Long epochDuration; private Long epochDuration;
public Long iRCandidateFee; private Long iRCandidateFee;
public Long maxObjectSize; private Long maxObjectSize;
public Long maxECDataCount; private Long maxECDataCount;
public Long maxECParityCount; private Long maxECParityCount;
public Long withdrawalFee; private Long withdrawalFee;
public Boolean homomorphicHashingDisabled; private Boolean homomorphicHashingDisabled;
public Boolean maintenanceModeAllowed; private Boolean maintenanceModeAllowed;
public Map<String, Object> unnamedSettings = new HashMap<>(); private Map<String, Object> unnamedSettings = new HashMap<>();
public Long getAuditFee() { public Long getAuditFee() {
return auditFee; return auditFee;
@ -77,11 +77,11 @@ public class NetworkSettings {
this.epochDuration = epochDuration; this.epochDuration = epochDuration;
} }
public long getiRCandidateFee() { public long getIRCandidateFee() {
return iRCandidateFee; return iRCandidateFee;
} }
public void setiRCandidateFee(long iRCandidateFee) { public void setIRCandidateFee(long iRCandidateFee) {
this.iRCandidateFee = iRCandidateFee; this.iRCandidateFee = iRCandidateFee;
} }

View file

@ -1,6 +1,7 @@
package info.frostfs.sdk.jdo; package info.frostfs.sdk.jdo;
import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.dto.session.SessionToken;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -8,11 +9,18 @@ import static java.util.Objects.isNull;
public class PutObjectParameters { public class PutObjectParameters {
private static final String ERROR_TEMPLATE = "%s value cannot be null."; 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; private ObjectHeader header;
public FileInputStream payload; private FileInputStream payload;
public boolean clientCut; private boolean clientCut;
public int bufferMaxSize; 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) { public PutObjectParameters(ObjectHeader header, FileInputStream payload, boolean clientCut, int bufferMaxSize) {
this.header = header; this.header = header;
@ -30,6 +38,46 @@ public class PutObjectParameters {
validate(); 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() { public ObjectHeader getHeader() {
return header; return header;
} }
@ -66,11 +114,11 @@ public class PutObjectParameters {
StringBuilder errorMessage = new StringBuilder(); StringBuilder errorMessage = new StringBuilder();
if (isNull(header)) { 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)) { 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) { if (errorMessage.length() != 0) {

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -14,7 +14,9 @@ public interface ObjectClient {
ObjectId putObject(PutObjectParameters parameters); ObjectId putObject(PutObjectParameters parameters);
ObjectId putSingleObject(ObjectFrostFS objectFrostFS);
void deleteObject(ContainerId containerId, ObjectId objectId); void deleteObject(ContainerId containerId, ObjectId objectId);
Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters); Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters);
} }

View file

@ -1,6 +1,6 @@
package info.frostfs.sdk.services; package info.frostfs.sdk.services;
import info.frostfs.sdk.dto.SessionToken; import info.frostfs.sdk.dto.session.SessionToken;
public interface SessionClient { public interface SessionClient {
SessionToken createSession(long expiration); SessionToken createSession(long expiration);

View file

@ -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);
}

View file

@ -2,48 +2,60 @@ package info.frostfs.sdk.services.impl;
import frostfs.container.ContainerServiceGrpc; import frostfs.container.ContainerServiceGrpc;
import frostfs.container.Service; import frostfs.container.Service;
import frostfs.refs.Types;
import info.frostfs.sdk.dto.container.Container; import info.frostfs.sdk.dto.container.Container;
import info.frostfs.sdk.dto.container.ContainerId; 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.jdo.ClientEnvironment;
import info.frostfs.sdk.mappers.OwnerIdMapper; import info.frostfs.sdk.jdo.WaitParameters;
import info.frostfs.sdk.mappers.VersionMapper;
import info.frostfs.sdk.mappers.container.ContainerIdMapper; import info.frostfs.sdk.mappers.container.ContainerIdMapper;
import info.frostfs.sdk.mappers.container.ContainerMapper; 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.ContainerClient;
import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.ContextAccessor;
import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestConstructor;
import info.frostfs.sdk.tools.RequestSigner; import info.frostfs.sdk.tools.RequestSigner;
import info.frostfs.sdk.tools.Verifier; import info.frostfs.sdk.tools.Verifier;
import info.frostfs.sdk.utils.WaitUtil;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
public class ContainerClientImpl extends ContextAccessor implements ContainerClient { 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 ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;
private final SessionToolsImpl sessionTools;
public ContainerClientImpl(ClientEnvironment clientEnvironment) { public ContainerClientImpl(ClientEnvironment clientEnvironment) {
super(clientEnvironment); super(clientEnvironment);
this.serviceBlockingStub = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel()); 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 @Override
public Container getContainer(ContainerId cid) { public Container getContainer(ContainerId cid) {
if (isNull(cid)) { if (isNull(cid)) {
throw new IllegalArgumentException("ContainerId is not present"); throw new IllegalArgumentException(ERROR_CONTAINER_ID_MISSING);
} }
var body = Service.GetRequest.Body.newBuilder() var request = createGetRequest(ContainerIdMapper.toGrpcMessage(cid), null);
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
.build();
var request = Service.GetRequest.newBuilder()
.setBody(body);
RequestConstructor.addDefaultMetaHeader(request); var response = serviceBlockingStub.get(request);
RequestSigner.sign(request, getContext().getKey());
var response = serviceBlockingStub.get(request.build());
Verifier.checkResponse(response); Verifier.checkResponse(response);
return ContainerMapper.toModel(response.getBody().getContainer()); return ContainerMapper.toModel(response.getBody().getContainer());
@ -51,16 +63,9 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
@Override @Override
public List<ContainerId> listContainers() { public List<ContainerId> listContainers() {
var body = Service.ListRequest.Body.newBuilder() var request = createListRequest(null);
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.build();
var request = Service.ListRequest.newBuilder()
.setBody(body);
RequestConstructor.addDefaultMetaHeader(request); var response = serviceBlockingStub.list(request);
RequestSigner.sign(request, getContext().getKey());
var response = serviceBlockingStub.list(request.build());
Verifier.checkResponse(response); Verifier.checkResponse(response);
@ -72,51 +77,155 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
@Override @Override
public ContainerId createContainer(Container container) { public ContainerId createContainer(Container container) {
if (isNull(container)) { if (isNull(container)) {
throw new IllegalArgumentException("Container is not present"); throw new IllegalArgumentException(ERROR_CONTAINER_MISSING);
} }
var grpcContainer = ContainerMapper.toGrpcMessage(container); var grpcContainer = ContainerMapper.toGrpcMessage(container);
grpcContainer = grpcContainer.toBuilder() var request = createPutRequest(grpcContainer, null);
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
.build();
var body = Service.PutRequest.Body.newBuilder() var response = serviceBlockingStub.put(request);
.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());
Verifier.checkResponse(response); Verifier.checkResponse(response);
waitForContainer(WaitExpects.EXISTS, response.getBody().getContainerId(), null);
return new ContainerId(response.getBody().getContainerId().getValue().toByteArray()); return new ContainerId(response.getBody().getContainerId().getValue().toByteArray());
} }
@Override @Override
public void deleteContainer(ContainerId cid) { public void deleteContainer(ContainerId cid) {
if (isNull(cid)) { if (isNull(cid)) {
throw new IllegalArgumentException("ContainerId is not present"); throw new IllegalArgumentException(ERROR_CONTAINER_ID_MISSING);
} }
var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid); 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() var body = Service.DeleteRequest.Body.newBuilder()
.setContainerId(grpcContainerId) .setContainerId(cid)
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), grpcContainerId.getValue())) .setSignature(RequestSigner.signRFC6979(getContext().getKey(), cid.getValue()))
.build(); .build();
var request = Service.DeleteRequest.newBuilder() var request = Service.DeleteRequest.newBuilder()
.setBody(body); .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()); RequestSigner.sign(request, getContext().getKey());
var response = serviceBlockingStub.delete(request.build()); return request.build();
Verifier.checkResponse(response);
} }
} }

View file

@ -67,7 +67,7 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
settings.setEpochDuration(getLongValue(valueBytes)); settings.setEpochDuration(getLongValue(valueBytes));
break; break;
case "InnerRingCandidateFee": case "InnerRingCandidateFee":
settings.setiRCandidateFee(getLongValue(valueBytes)); settings.setIRCandidateFee(getLongValue(valueBytes));
break; break;
case "MaxECDataCount": case "MaxECDataCount":
settings.setMaxECDataCount(getLongValue(valueBytes)); settings.setMaxECDataCount(getLongValue(valueBytes));
@ -114,10 +114,9 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
@Override @Override
public NodeInfo getLocalNodeInfo() { public NodeInfo getLocalNodeInfo() {
var request = Service.LocalNodeInfoRequest.newBuilder() var request = Service.LocalNodeInfoRequest.newBuilder();
.setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build());
RequestConstructor.addDefaultMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
var response = netmapServiceClient.localNodeInfo(request.build()); var response = netmapServiceClient.localNodeInfo(request.build());
@ -127,10 +126,9 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
} }
public Service.NetworkInfoResponse getNetworkInfo() { public Service.NetworkInfoResponse getNetworkInfo() {
var request = Service.NetworkInfoRequest.newBuilder() var request = Service.NetworkInfoRequest.newBuilder();
.setBody(Service.NetworkInfoRequest.Body.newBuilder().build());
RequestConstructor.addDefaultMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
var response = netmapServiceClient.networkInfo(request.build()); var response = netmapServiceClient.networkInfo(request.build());
@ -142,10 +140,9 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
@Override @Override
public NetmapSnapshot getNetmapSnapshot() { public NetmapSnapshot getNetmapSnapshot() {
var request = Service.NetmapSnapshotRequest.newBuilder() var request = Service.NetmapSnapshotRequest.newBuilder();
.setBody(Service.NetmapSnapshotRequest.Body.newBuilder().build());
RequestConstructor.addDefaultMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
var response = netmapServiceClient.netmapSnapshot(request.build()); var response = netmapServiceClient.netmapSnapshot(request.build());

View file

@ -6,21 +6,22 @@ import frostfs.object.ObjectServiceGrpc;
import frostfs.object.Service; import frostfs.object.Service;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.constants.AppConst; import info.frostfs.sdk.constants.AppConst;
import info.frostfs.sdk.dto.Split;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.dto.object.*; 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.ClientEnvironment;
import info.frostfs.sdk.jdo.PutObjectParameters; import info.frostfs.sdk.jdo.PutObjectParameters;
import info.frostfs.sdk.mappers.OwnerIdMapper; import info.frostfs.sdk.jdo.PutObjectResult;
import info.frostfs.sdk.mappers.VersionMapper;
import info.frostfs.sdk.mappers.container.ContainerIdMapper; import info.frostfs.sdk.mappers.container.ContainerIdMapper;
import info.frostfs.sdk.mappers.object.ObjectFilterMapper; import info.frostfs.sdk.mappers.object.ObjectFilterMapper;
import info.frostfs.sdk.mappers.object.ObjectFrostFSMapper; import info.frostfs.sdk.mappers.object.ObjectFrostFSMapper;
import info.frostfs.sdk.mappers.object.ObjectHeaderMapper; import info.frostfs.sdk.mappers.object.ObjectHeaderMapper;
import info.frostfs.sdk.mappers.object.ObjectIdMapper; 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.ContextAccessor;
import info.frostfs.sdk.services.ObjectClient; 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.ObjectWriter;
import info.frostfs.sdk.services.impl.rwhelper.SearchReader; import info.frostfs.sdk.services.impl.rwhelper.SearchReader;
import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestConstructor;
@ -30,44 +31,42 @@ import org.apache.commons.collections4.CollectionUtils;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static info.frostfs.sdk.Helper.getSha256; 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 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 { 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.ObjectServiceBlockingStub objectServiceBlockingClient;
private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient;
private final ObjectToolsImpl objectToolsImpl; private final ObjectToolsImpl objectToolsImpl;
private final SessionToolsImpl sessionTools;
public ObjectClientImpl(ClientEnvironment clientEnvironment) { public ObjectClientImpl(ClientEnvironment clientEnvironment) {
super(clientEnvironment); super(clientEnvironment);
this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(getContext().getChannel()); this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(getContext().getChannel());
this.objectServiceClient = ObjectServiceGrpc.newStub(getContext().getChannel()); this.objectServiceClient = ObjectServiceGrpc.newStub(getContext().getChannel());
this.objectToolsImpl = new ObjectToolsImpl(clientEnvironment); this.objectToolsImpl = new ObjectToolsImpl(clientEnvironment);
this.sessionTools = new SessionToolsImpl(clientEnvironment);
}
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) {
return sessionTools.getOrCreateSession(sessionToken, getContext());
} }
@Override @Override
public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) { public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) {
var address = Types.Address.newBuilder() if (isNull(cid) || isNull(oid)) {
.setContainerId(ContainerIdMapper.toGrpcMessage(cid)) throw new IllegalArgumentException(ERROR_PARAMS_MISSING);
.setObjectId(ObjectIdMapper.toGrpcMessage(oid)) }
.build();
var body = Service.HeadRequest.Body.newBuilder()
.setAddress(address)
.build();
var request = Service.HeadRequest.newBuilder()
.setBody(body);
RequestConstructor.addDefaultMetaHeader(request); var request = createHeadRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
sign(request, getContext().getKey());
var response = objectServiceBlockingClient.head(request);
var response = objectServiceBlockingClient.head(request.build());
Verifier.checkResponse(response); Verifier.checkResponse(response);
return ObjectHeaderMapper.toModel(response.getBody().getHeader().getHeader()); return ObjectHeaderMapper.toModel(response.getBody().getHeader().getHeader());
@ -75,66 +74,25 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
@Override @Override
public ObjectFrostFS getObject(ContainerId cid, ObjectId oid) { 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() return getObject(request);
.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);
} }
@Override @Override
public void deleteObject(ContainerId cid, ObjectId oid) { public void deleteObject(ContainerId cid, ObjectId oid) {
var address = Types.Address.newBuilder() var request = createDeleteRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
.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);
RequestConstructor.addDefaultMetaHeader(request); var response = objectServiceBlockingClient.delete(request);
sign(request, getContext().getKey());
var response = objectServiceBlockingClient.delete(request.build());
Verifier.checkResponse(response); Verifier.checkResponse(response);
} }
@Override @Override
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters) { public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter... filters) {
var body = Service.SearchRequest.Body.newBuilder() var request = createSearchRequest(ContainerIdMapper.toGrpcMessage(cid), filters);
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
.setVersion(1);// TODO: clarify this param
for (ObjectFilter filter : filters) { var objectsIds = searchObjects(request);
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());
return Iterables.transform(objectsIds, input -> new ObjectId(input.getValue().toByteArray())); 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) { public ObjectId putObject(PutObjectParameters parameters) {
parameters.validate(); parameters.validate();
return parameters.clientCut ? putClientCutObject(parameters) : putStreamObject(parameters); if (parameters.isClientCut()) {
return putClientCutObject(parameters);
}
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) { public ObjectId putSingleObject(ObjectFrostFS modelObject) {
var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1);
var grpcObject = objectToolsImpl.createObject(modelObject); var grpcObject = objectToolsImpl.createObject(modelObject);
var request = Service.PutSingleRequest.newBuilder() var request = createPutSingleRequest(grpcObject);
.setBody(Service.PutSingleRequest.Body.newBuilder().setObject(grpcObject).build());
var response = objectServiceBlockingClient.putSingle(request);
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());
Verifier.checkResponse(response); Verifier.checkResponse(response);
return new ObjectId(grpcObject.getObjectId().getValue().toByteArray()); return new ObjectId(grpcObject.getObjectId().getValue().toByteArray());
} }
private frostfs.object.Types.Object getObject(Service.GetRequest request) { private ObjectFrostFS getObject(Service.GetRequest request) {
var iterator = getObjectInit(request); var reader = getObjectInit(request);
var obj = iterator.readHeader();
var payload = new byte[Math.toIntExact(obj.getHeader().getPayloadLength())];
var offset = 0;
var chunk = iterator.readChunk();
while (nonNull(chunk)) { var grpcObject = reader.readHeader();
System.arraycopy(chunk, 0, payload, offset, chunk.length); var modelObject = ObjectFrostFSMapper.toModel(grpcObject);
offset += chunk.length;
chunk = iterator.readChunk();
}
return obj.toBuilder().setPayload(ByteString.copyFrom(payload)).build(); modelObject.setObjectReader(reader);
return modelObject;
} }
private ObjectReader getObjectInit(Service.GetRequest initRequest) { private ObjectReaderImpl getObjectInit(Service.GetRequest initRequest) {
if (initRequest.getSerializedSize() == 0) { if (initRequest.getSerializedSize() == 0) {
throw new IllegalArgumentException(initRequest.getClass().getName()); throw new IllegalArgumentException(initRequest.getClass().getName());
} }
return new ObjectReader(objectServiceBlockingClient.get(initRequest)); return new ObjectReaderImpl(objectServiceBlockingClient.get(initRequest));
} }
private ObjectId putStreamObject(PutObjectParameters parameters) { private PutObjectResult putStreamObject(PutObjectParameters parameters) {
var header = parameters.getHeader(); 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); chunkSize = (int) Math.min(restBytes, chunkSize);
hdr = hdr.toBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
.build();
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() var sentBytes = 0;
.setBody(
Service.PutRequest.Body.newBuilder()
.setInit(
Service.PutRequest.Body.Init.newBuilder().setHeader(hdr).build()
).build()
);
RequestConstructor.addDefaultMetaHeader(initRequest); // 0 means no limit from client, so server side cut is performed
addObjectSessionToken( var objectLimitSize = parameters.isClientCut() ? parameters.getMaxObjectSizeCache() : 0;
initRequest, sessionToken, hdr.getContainerId(), oid,
frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey()
);
sign(initRequest, getContext().getKey());
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; var bytesCount = readNBytes(parameters.getPayload(), chunkBuffer, bufferSize);
bufferSize = (int) Math.min(getStreamSize(parameters.getPayload()), bufferSize);
bufferSize = header.getPayloadLength() > 0 ? (int) Math.min(header.getPayloadLength(), bufferSize) : bufferSize;
var buffer = new byte[bufferSize]; if (bytesCount == 0) {
while (true) {
var bytesCount = readNBytes(parameters.getPayload(), buffer, bufferSize);
if (bytesCount <= 0) {
break; break;
} }
var chunkRequest = Service.PutRequest.newBuilder(initRequest.build()) sentBytes += bytesCount;
.setBody(
Service.PutRequest.Body.newBuilder() var body = Service.PutRequest.Body.newBuilder()
.setChunk(ByteString.copyFrom(Arrays.copyOfRange(buffer, 0, bytesCount))) .setChunk(ByteString.copyFrom(chunkBuffer, 0, bytesCount))
.build() .build();
) var chunkRequest = Service.PutRequest.newBuilder()
.setBody(body)
.clearVerifyHeader(); .clearVerifyHeader();
sign(chunkRequest, getContext().getKey()); sign(chunkRequest, getContext().getKey());
writer.write(chunkRequest.build());
stream.write(chunkRequest.build());
} }
var response = writer.complete(); var response = stream.complete();
Verifier.checkResponse(response); 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) { private ObjectId putClientCutObject(PutObjectParameters parameters) {
var header = parameters.getHeader(); var header = parameters.getHeader();
var tokenRaw = getOrCreateSession(parameters.getSessionToken());
var token = new SessionToken(SessionMapper.serialize(tokenRaw));
parameters.setSessionToken(token);
var networkSettings = getContext().getFrostFSClient().getNetworkSettings(); var fullLength = header.getPayloadLength() == 0
var payloadSize = getStreamSize(parameters.getPayload()); ? getStreamSize(parameters.getPayload())
var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize()); : header.getPayloadLength();
var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength();
if (fullLength == 0) { parameters.setFullLength(fullLength);
throw new IllegalArgumentException(ERROR_PAYLOAD);
if (parameters.getMaxObjectSizeCache() == 0) {
var networkSettings = getContext().getFrostFSClient().getNetworkSettings();
parameters.setMaxObjectSizeCache((int) networkSettings.getMaxObjectSize());
} }
var buffer = new byte[objectSize]; var restBytes = fullLength - parameters.getCurrentStreamPosition();
var largeObject = new LargeObject(header.getContainerId()); var objectSize = restBytes > 0
var split = new Split(); ? Math.min(parameters.getMaxObjectSizeCache(), restBytes)
: parameters.getMaxObjectSizeCache();
ObjectId objectId; //define collection capacity
List<ObjectId> sentObjectIds = new ArrayList<>(); var restPart = (restBytes % objectSize) > 0 ? 1 : 0;
ObjectFrostFS currentObject; var objectsCount = fullLength > 0 ? (int) (restBytes / objectSize) + restPart : 0;
while (true) { List<ObjectId> sentObjectIds = new ArrayList<>(objectsCount);
var bytesCount = readNBytes(parameters.getPayload(), buffer, objectSize);
if (CollectionUtils.isNotEmpty(sentObjectIds)) {
split.setPrevious(sentObjectIds.get(sentObjectIds.size() - 1));
}
largeObject.appendBlock(buffer, bytesCount); // keep attributes for the large object
var attributes = parameters.getHeader().getAttributes();
currentObject = new ObjectFrostFS( Split split = new Split();
header.getContainerId(), parameters.getHeader().setSplit(split);
bytesCount < objectSize ? Arrays.copyOfRange(buffer, 0, bytesCount) : buffer parameters.getHeader().setAttributes(new ArrayList<>());
);
currentObject.setSplit(split);
if (largeObject.getPayloadLength() == fullLength) { // send all parts except the last one as separate Objects
break; while (restBytes > (long) parameters.getMaxObjectSizeCache()) {
} var previous = CollectionUtils.isNotEmpty(sentObjectIds)
? sentObjectIds.get(sentObjectIds.size() - 1)
: null;
split.setPrevious(previous);
objectId = putSingleObject(currentObject); var result = putStreamObject(parameters);
sentObjectIds.add(objectId); sentObjectIds.add(result.getObjectId());
restBytes -= result.getObjectSize();
} }
if (CollectionUtils.isEmpty(sentObjectIds)) { // send the last part and create linkObject
currentObject.addAttributes(parameters.getHeader().getAttributes()); if (CollectionUtils.isNotEmpty(sentObjectIds)) {
return putSingleObject(currentObject); var largeObjectHeader =
new ObjectHeader(header.getContainerId(), ObjectType.REGULAR, attributes, fullLength, null);
split.setParentHeader(largeObjectHeader);
var result = putStreamObject(parameters);
sentObjectIds.add(result.getObjectId());
var linkObject = new LinkObject(header.getContainerId(), split.getSplitId(), largeObjectHeader);
linkObject.addChildren(sentObjectIds);
putSingleObject(linkObject);
return split.getParent();
} }
largeObject.addAttributes(parameters.getHeader().getAttributes()); // We are here if the payload is placed to one Object. It means no cut action, just simple PUT.
largeObject.calculateHash(); var singlePartResult = putStreamObject(parameters);
currentObject.setParent(largeObject); return singlePartResult.getObjectId();
}
objectId = putSingleObject(currentObject); private ObjectWriter getUploadStream(PutObjectParameters parameters) {
var header = parameters.getHeader();
sentObjectIds.add(objectId); header.setOwnerId(getContext().getOwnerId());
header.setVersion(getContext().getVersion());
var linkObject = new LinkObject(header.getContainerId(), split.getSplitId(), largeObject); var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header);
linkObject.addChildren(sentObjectIds); grpcHeader = objectToolsImpl.updateSplitValues(grpcHeader, header.getSplit());
linkObject.getHeader().getAttributes().clear(); var oid = Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build();
putSingleObject(linkObject); var initRequest = createInitPutRequest(oid, grpcHeader);
return objectToolsImpl.calculateObjectId(largeObject.getHeader()); return putObjectInit(initRequest);
} }
private ObjectWriter putObjectInit(Service.PutRequest initRequest) { private ObjectWriter putObjectInit(Service.PutRequest initRequest) {
@ -333,12 +300,12 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
var ids = reader.read(); var ids = reader.read();
List<Types.ObjectID> result = new ArrayList<>(); List<Types.ObjectID> result = new ArrayList<>();
while (nonNull(ids) && !ids.isEmpty()) { while (CollectionUtils.isNotEmpty(ids)) {
result.addAll(ids); result.addAll(ids);
ids = reader.read(); ids = reader.read();
} }
return result; return result;//todo return yield
} }
private SearchReader getSearchReader(Service.SearchRequest initRequest) { private SearchReader getSearchReader(Service.SearchRequest initRequest) {
@ -364,4 +331,168 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
throw new IllegalArgumentException(exp.getMessage()); 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();
}
} }

View file

@ -5,17 +5,21 @@ import frostfs.object.Types;
import info.frostfs.sdk.dto.object.ObjectFrostFS; import info.frostfs.sdk.dto.object.ObjectFrostFS;
import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.dto.object.ObjectId; import info.frostfs.sdk.dto.object.ObjectId;
import info.frostfs.sdk.dto.object.Split;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.mappers.OwnerIdMapper; import info.frostfs.sdk.mappers.netmap.VersionMapper;
import info.frostfs.sdk.mappers.VersionMapper;
import info.frostfs.sdk.mappers.object.ObjectHeaderMapper; import info.frostfs.sdk.mappers.object.ObjectHeaderMapper;
import info.frostfs.sdk.mappers.object.ObjectIdMapper; 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.ContextAccessor;
import info.frostfs.sdk.services.ToolsClient; 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.Helper.getSha256;
import static info.frostfs.sdk.tools.RequestSigner.signData; import static info.frostfs.sdk.tools.RequestSigner.signData;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
public class ObjectToolsImpl extends ContextAccessor implements ToolsClient { public class ObjectToolsImpl extends ContextAccessor implements ToolsClient {
@ -34,52 +38,29 @@ public class ObjectToolsImpl extends ContextAccessor implements ToolsClient {
public ObjectId calculateObjectId(ObjectHeader header) { public ObjectId calculateObjectId(ObjectHeader header) {
var grpcHeader = createHeader(header, new byte[]{}); var grpcHeader = createHeader(header, new byte[]{});
if (nonNull(header.getSplit())) {
grpcHeader = updateSplitValues(grpcHeader, header.getSplit());
}
return ObjectIdMapper.toModel( return ObjectIdMapper.toModel(
frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build() frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build()
); );
} }
public Types.Object createObject(ObjectFrostFS objectFrostFs) { public Types.Object createObject(ObjectFrostFS objectFrostFs) {
var grpcHeaderBuilder = ObjectHeaderMapper.toGrpcMessage(objectFrostFs.getHeader()).toBuilder() objectFrostFs.getHeader().setOwnerId(getContext().getOwnerId());
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) objectFrostFs.getHeader().setVersion(getContext().getVersion());
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())) objectFrostFs.getHeader().setPayloadLength(objectFrostFs.getPayload().length);
.setPayloadLength(objectFrostFs.getPayload().length)
.setPayloadHash(sha256Checksum(objectFrostFs.getPayload())); var grpcHeader = ObjectHeaderMapper.toGrpcMessage(objectFrostFs.getHeader()).toBuilder()
.setPayloadHash(sha256Checksum(objectFrostFs.getPayload()))
.build();
var split = objectFrostFs.getHeader().getSplit(); var split = objectFrostFs.getHeader().getSplit();
if (nonNull(split)) { if (nonNull(split)) {
var splitGrpc = Types.Header.Split.newBuilder() grpcHeader = updateSplitValues(grpcHeader, split);
.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);
} }
var grpcHeader = grpcHeaderBuilder.build();
var objectId = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build(); var objectId = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build();
var sig = frostfs.refs.Types.Signature.newBuilder() var sig = frostfs.refs.Types.Signature.newBuilder()
.setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte()))
@ -92,14 +73,48 @@ public class ObjectToolsImpl extends ContextAccessor implements ToolsClient {
.build(); .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) { private Types.Header createHeader(ObjectHeader header, byte[] payload) {
var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header).toBuilder() var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header).toBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())); .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()));
if (header.getPayloadCheckSum() != null) { if (payload != null) {
grpcHeader.setPayloadHash(sha256Checksum(header.getPayloadCheckSum()));
} else if (payload != null) {
grpcHeader.setPayloadHash(sha256Checksum(payload)); grpcHeader.setPayloadHash(sha256Checksum(payload));
} }

View file

@ -3,13 +3,14 @@ package info.frostfs.sdk.services.impl;
import frostfs.session.Service; import frostfs.session.Service;
import frostfs.session.SessionServiceGrpc; import frostfs.session.SessionServiceGrpc;
import frostfs.session.Types; 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.jdo.ClientEnvironment;
import info.frostfs.sdk.mappers.OwnerIdMapper; import info.frostfs.sdk.mappers.object.OwnerIdMapper;
import info.frostfs.sdk.mappers.SessionMapper; import info.frostfs.sdk.mappers.session.SessionMapper;
import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.ContextAccessor;
import info.frostfs.sdk.services.SessionClient; import info.frostfs.sdk.services.SessionClient;
import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestConstructor;
import info.frostfs.sdk.tools.Verifier;
import static info.frostfs.sdk.tools.RequestSigner.sign; import static info.frostfs.sdk.tools.RequestSigner.sign;
@ -25,7 +26,7 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
public SessionToken createSession(long expiration) { public SessionToken createSession(long expiration) {
var sessionToken = createSessionInternal(expiration); var sessionToken = createSessionInternal(expiration);
var token = SessionMapper.serialize(sessionToken); var token = SessionMapper.serialize(sessionToken);
return new SessionToken(new byte[]{}, token); return new SessionToken(token);
} }
public Types.SessionToken createSessionInternal(long expiration) { public Types.SessionToken createSessionInternal(long expiration) {
@ -36,24 +37,26 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
var request = Service.CreateRequest.newBuilder() var request = Service.CreateRequest.newBuilder()
.setBody(body); .setBody(body);
RequestConstructor.addDefaultMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return createSession(request.build()); return createSession(request.build());
} }
private Types.SessionToken createSession(Service.CreateRequest request) { 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() var lifetime = Types.SessionToken.Body.TokenLifetime.newBuilder()
.setExp(request.getBody().getExpiration()) .setExp(request.getBody().getExpiration())
.setIat(resp.getMetaHeader().getEpoch()) .setIat(response.getMetaHeader().getEpoch())
.setNbf(resp.getMetaHeader().getEpoch()) .setNbf(response.getMetaHeader().getEpoch())
.build(); .build();
var body = Types.SessionToken.Body.newBuilder() var body = Types.SessionToken.Body.newBuilder()
.setId(resp.getBody().getId()) .setId(response.getBody().getId())
.setSessionKey(resp.getBody().getSessionKey()) .setSessionKey(response.getBody().getSessionKey())
.setOwnerId(request.getBody().getOwnerId()) .setOwnerId(request.getBody().getOwnerId())
.setLifetime(lifetime) .setLifetime(lifetime)
.build(); .build();

View file

@ -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());
}
}

View file

@ -2,17 +2,18 @@ package info.frostfs.sdk.services.impl.rwhelper;
import frostfs.object.Service; import frostfs.object.Service;
import frostfs.object.Types; import frostfs.object.Types;
import info.frostfs.sdk.dto.object.ObjectReader;
import info.frostfs.sdk.tools.Verifier; import info.frostfs.sdk.tools.Verifier;
import java.util.Iterator; 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_STREAM = "unexpected end of stream";
public static final String ERROR_UNEXPECTED_MESSAGE_TYPE = "unexpected message type"; public static final String ERROR_UNEXPECTED_MESSAGE_TYPE = "unexpected message type";
public Iterator<Service.GetResponse> call; public Iterator<Service.GetResponse> call;
public ObjectReader(Iterator<Service.GetResponse> call) { public ObjectReaderImpl(Iterator<Service.GetResponse> call) {
this.call = call; this.call = call;
} }

View file

@ -2,11 +2,13 @@ package info.frostfs.sdk.services.impl.rwhelper;
import frostfs.object.ObjectServiceGrpc; import frostfs.object.ObjectServiceGrpc;
import frostfs.object.Service; import frostfs.object.Service;
import info.frostfs.sdk.utils.WaitUtil;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
public class ObjectWriter { public class ObjectWriter {
private static final long POLL_INTERVAL = 10;
private final StreamObserver<Service.PutRequest> requestObserver; private final StreamObserver<Service.PutRequest> requestObserver;
private final PutResponseCallback responseObserver; private final PutResponseCallback responseObserver;
@ -29,7 +31,7 @@ public class ObjectWriter {
requestObserver.onCompleted(); requestObserver.onCompleted();
while (isNull(responseObserver.getResponse())) { while (isNull(responseObserver.getResponse())) {
System.out.println("Waiting response"); WaitUtil.sleep(POLL_INTERVAL);
} }
return responseObserver.getResponse(); return responseObserver.getResponse();

View file

@ -3,6 +3,7 @@ package info.frostfs.sdk.tools;
import io.grpc.Channel; import io.grpc.Channel;
import io.grpc.ChannelCredentials; import io.grpc.ChannelCredentials;
import io.grpc.netty.NettyChannelBuilder; import io.grpc.netty.NettyChannelBuilder;
import org.apache.commons.lang3.StringUtils;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
@ -11,17 +12,23 @@ import static java.util.Objects.isNull;
public class GrpcClient { public class GrpcClient {
private static final String ERROR_INVALID_HOST_TEMPLATE = "Host %s has invalid format. Error: %s"; 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() { 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 { try {
URI uri = new URI(host); URI uri = new URI(host);
var channelBuilder = isNull(creds) ? NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()) var channelBuilder = isNull(credentials)
: NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort(), creds); ? NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()).usePlaintext()
: NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort(), credentials);
return channelBuilder.usePlaintext().build(); return channelBuilder.build();
} catch (URISyntaxException exp) { } catch (URISyntaxException exp) {
throw new IllegalArgumentException(String.format(ERROR_INVALID_HOST_TEMPLATE, host, exp.getMessage())); throw new IllegalArgumentException(String.format(ERROR_INVALID_HOST_TEMPLATE, host, exp.getMessage()));
} }

View file

@ -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);
}
}

View file

@ -1,63 +1,130 @@
package info.frostfs.sdk.tools; package info.frostfs.sdk.tools;
import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import frostfs.session.Types; 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.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.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.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.isNull;
import static java.util.Objects.nonNull;
public class RequestConstructor { public class RequestConstructor {
private static final String ERROR_MESSAGE = "The message does not contain a field " + META_HEADER_FIELD_NAME;
private RequestConstructor() { private RequestConstructor() {
} }
public static void addDefaultMetaHeader(Message.Builder request) { public static void addMetaHeader(Message.Builder request) {
addMetaHeader(request, null); 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)) { if (isNull(request)) {
return; return;
} }
if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) { if (isNull(request.getDescriptorForType().findFieldByName(META_HEADER_FIELD_NAME))) {
metaHeader = MetaHeaderMapper.toGrpcMessage(new MetaHeader()); throw new IllegalArgumentException(ERROR_MESSAGE);
setField(request, META_HEADER_FIELD_NAME, metaHeader);
} }
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 void addObjectSessionToken(Message.Builder request, public static Types.SessionToken createObjectTokenContext(Types.SessionToken sessionToken,
Types.SessionToken sessionToken, frostfs.refs.Types.Address address,
frostfs.refs.Types.ContainerID cid, Types.ObjectSessionContext.Verb verb,
frostfs.refs.Types.ObjectID oid, ECDsa key) {
Types.ObjectSessionContext.Verb verb, if (isNull(sessionToken) || sessionToken.getBody().getObject().getTarget().getSerializedSize() > 0) {
ECDsa key) { return sessionToken;
if (isNull(request) || isNull(sessionToken)) {
return;
} }
var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME); var target = Types.ObjectSessionContext.Target.newBuilder()
if (header.getSessionToken().getSerializedSize() > 0) { .setContainer(address.getContainerId());
return;
if (address.getObjectId().getSerializedSize() > 0) {
target.addObjects(address.getObjectId());
} }
var ctx = Types.ObjectSessionContext.newBuilder() var ctx = Types.ObjectSessionContext.newBuilder()
.setTarget(Types.ObjectSessionContext.Target.newBuilder().setContainer(cid).addObjects(oid).build()) .setTarget(target.build())
.setVerb(verb) .setVerb(verb)
.build(); .build();
var body = sessionToken.getBody().toBuilder()
.setObject(ctx)
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()))
.build();
var body = sessionToken.getBody().toBuilder().setObject(ctx).build(); return sessionToken.toBuilder()
sessionToken = sessionToken.toBuilder()
.setSignature(signMessagePart(key, body)) .setSignature(signMessagePart(key, body))
.setBody(body) .setBody(body)
.build(); .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();
} }
} }

View file

@ -5,6 +5,7 @@ import com.google.protobuf.Message;
import frostfs.session.Types; import frostfs.session.Types;
import info.frostfs.sdk.constants.CryptoConst; import info.frostfs.sdk.constants.CryptoConst;
import info.frostfs.sdk.jdo.ECDsa; import info.frostfs.sdk.jdo.ECDsa;
import info.frostfs.sdk.utils.MessageHelper;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
@ -92,10 +93,10 @@ public class RequestSigner {
} }
public static void sign(Message.Builder request, ECDsa key) { public static void sign(Message.Builder request, ECDsa key) {
var meta = MessageHelper.getField(request, META_HEADER_FIELD_NAME); var meta = (Message) MessageHelper.getField(request, META_HEADER_FIELD_NAME);
var body = MessageHelper.getField(request, BODY_FIELD_NAME); var body = (Message) MessageHelper.getField(request, BODY_FIELD_NAME);
var verify = MessageHelper.getField(request, VERIFY_HEADER_FIELD_NAME); var verify = (Message) MessageHelper.getField(request, VERIFY_HEADER_FIELD_NAME);
var verifyOrigin = MessageHelper.getField(verify, ORIGIN_FIELD_NAME); var verifyOrigin = (Message) MessageHelper.getField(verify, ORIGIN_FIELD_NAME);
Message.Builder verifyBuilder; Message.Builder verifyBuilder;
if (verify instanceof Types.RequestVerificationHeader) { if (verify instanceof Types.RequestVerificationHeader) {

View file

@ -3,7 +3,9 @@ package info.frostfs.sdk.tools;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import frostfs.session.Types; import frostfs.session.Types;
import info.frostfs.sdk.constants.CryptoConst; 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.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers; 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 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()) { if (!status.isSuccess()) {
throw new IllegalArgumentException(status.toString()); throw new ResponseException(status);
} }
} }
public static boolean verify(Message response) { 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 metaHeader = (Types.ResponseMetaHeader) MessageHelper.getField(response, META_HEADER_FIELD_NAME);
var verifyHeader = (Types.ResponseVerificationHeader) var verifyHeader = (Types.ResponseVerificationHeader)
MessageHelper.getField(response, VERIFY_HEADER_FIELD_NAME); MessageHelper.getField(response, VERIFY_HEADER_FIELD_NAME);

View file

@ -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);
}
}

View 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();
}
}
}

View file

@ -13,10 +13,10 @@ public class ArrayHelper {
throw new IllegalArgumentException(ERROR_MESSAGE); 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(startArray, 0, joinedArray, 0, startArray.length);
System.arraycopy(endArray, 0, result, startArray.length, endArray.length); System.arraycopy(endArray, 0, joinedArray, startArray.length, endArray.length);
return result; return joinedArray;
} }
} }

View file

@ -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";
}

View 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);
}
}

View file

@ -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;
}
}

View file

@ -1,7 +1,7 @@
package info.frostfs.sdk.dto.container; 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.PlacementPolicy;
import info.frostfs.sdk.dto.netmap.Version;
import info.frostfs.sdk.enums.BasicAcl; import info.frostfs.sdk.enums.BasicAcl;
import java.util.UUID; import java.util.UUID;

View file

@ -1,5 +1,6 @@
package info.frostfs.sdk.dto.netmap; package info.frostfs.sdk.dto.netmap;
import java.util.Collections;
import java.util.List; import java.util.List;
public class NetmapSnapshot { public class NetmapSnapshot {
@ -8,7 +9,7 @@ public class NetmapSnapshot {
public NetmapSnapshot(Long epoch, List<NodeInfo> nodeInfoCollection) { public NetmapSnapshot(Long epoch, List<NodeInfo> nodeInfoCollection) {
this.epoch = epoch; this.epoch = epoch;
this.nodeInfoCollection = nodeInfoCollection; this.nodeInfoCollection = Collections.unmodifiableList(nodeInfoCollection);
} }
public Long getEpoch() { public Long getEpoch() {

View file

@ -1,8 +1,8 @@
package info.frostfs.sdk.dto.netmap; package info.frostfs.sdk.dto.netmap;
import info.frostfs.sdk.dto.Version;
import info.frostfs.sdk.enums.NodeState; import info.frostfs.sdk.enums.NodeState;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -17,8 +17,8 @@ public class NodeInfo {
Map<String, String> attributes, byte[] publicKey) { Map<String, String> attributes, byte[] publicKey) {
this.state = state; this.state = state;
this.version = version; this.version = version;
this.addresses = addresses; this.addresses = Collections.unmodifiableList(addresses);
this.attributes = attributes; this.attributes = Collections.unmodifiableMap(attributes);
this.publicKey = publicKey; this.publicKey = publicKey;
} }

View file

@ -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_MAJOR_VERSION;
import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION; import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION;

View file

@ -1,7 +1,5 @@
package info.frostfs.sdk.dto.object; 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 info.frostfs.sdk.dto.container.ContainerId;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@ -9,10 +7,10 @@ import java.util.List;
public class LinkObject extends ObjectFrostFS { 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[]{}); super(cid, new byte[]{});
var split = new Split(splitId); var split = new Split(splitId);
split.setParentHeader(largeObject.getHeader()); split.setParentHeader(largeObjectHeader);
this.getHeader().setSplit(split); this.getHeader().setSplit(split);
} }

View file

@ -1,39 +1,24 @@
package info.frostfs.sdk.dto.object; package info.frostfs.sdk.dto.object;
import info.frostfs.sdk.dto.OwnerId; import info.frostfs.sdk.constants.FieldConst;
import info.frostfs.sdk.dto.Version; 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; import info.frostfs.sdk.enums.ObjectMatchType;
public class ObjectFilter { public abstract class ObjectFilter<T> {
private static final String HEADER_PREFIX = "$Object:";
private ObjectMatchType matchType; private ObjectMatchType matchType;
private String key; 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.matchType = matchType;
this.key = key; this.key = key;
this.value = value; 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() { public ObjectMatchType getMatchType() {
return matchType; return matchType;
} }
@ -50,11 +35,94 @@ public class ObjectFilter {
this.key = key; this.key = key;
} }
public String getValue() { public T getValue() {
return value; return value;
} }
public void setValue(String value) { public void setValue(T value) {
this.value = 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);
}
}
} }

View file

@ -1,10 +1,8 @@
package info.frostfs.sdk.dto.object; package info.frostfs.sdk.dto.object;
import info.frostfs.sdk.dto.Split;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.enums.ObjectType; import info.frostfs.sdk.enums.ObjectType;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
@ -13,6 +11,7 @@ public class ObjectFrostFS {
private final ObjectHeader header; private final ObjectHeader header;
private ObjectId objectId; private ObjectId objectId;
private byte[] payload; private byte[] payload;
private ObjectReader objectReader;
public ObjectFrostFS(ObjectHeader header, ObjectId objectId, byte[] payload) { public ObjectFrostFS(ObjectHeader header, ObjectId objectId, byte[] payload) {
if (isNull(header)) { if (isNull(header)) {
@ -26,12 +25,20 @@ public class ObjectFrostFS {
public ObjectFrostFS(ContainerId containerId, byte[] payload) { public ObjectFrostFS(ContainerId containerId, byte[] payload) {
this.payload = payload; this.payload = payload;
this.header = new ObjectHeader(containerId, new ArrayList<>()); this.header = new ObjectHeader(containerId);
} }
public ObjectFrostFS(ContainerId containerId, byte[] payload, ObjectType objectType) { public ObjectFrostFS(ContainerId containerId, byte[] payload, ObjectType objectType) {
this.payload = payload; 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() { public ObjectHeader getHeader() {

View file

@ -1,12 +1,12 @@
package info.frostfs.sdk.dto.object; 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.container.ContainerId;
import info.frostfs.sdk.dto.netmap.Version;
import info.frostfs.sdk.enums.ObjectType; import info.frostfs.sdk.enums.ObjectType;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
@ -33,24 +33,18 @@ public class ObjectHeader {
this.version = version; this.version = version;
} }
public ObjectHeader(ContainerId containerId, ObjectType objectType, List<ObjectAttribute> attributes) { public ObjectHeader(ContainerId containerId, ObjectType objectType, ObjectAttribute... attributes) {
if (isNull(containerId) || isNull(objectType)) { this(
throw new IllegalArgumentException("ContainerId or objectType is not present"); containerId,
} objectType,
Arrays.stream(attributes).collect(Collectors.toList()),
this.attributes = attributes; 0L,
this.containerId = containerId; null
this.objectType = objectType; );
} }
public ObjectHeader(ContainerId containerId, List<ObjectAttribute> attributes) { public ObjectHeader(ContainerId containerId, ObjectAttribute... attributes) {
if (isNull(containerId)) { this(containerId, ObjectType.REGULAR, attributes);
throw new IllegalArgumentException("ContainerId is not present");
}
this.attributes = attributes;
this.containerId = containerId;
this.objectType = ObjectType.REGULAR;
} }
public OwnerId getOwnerId() { public OwnerId getOwnerId() {

View file

@ -0,0 +1,5 @@
package info.frostfs.sdk.dto.object;
public interface ObjectReader {
byte[] readChunk();
}

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.dto; package info.frostfs.sdk.dto.object;
import info.frostfs.sdk.Base58; import info.frostfs.sdk.Base58;
@ -27,4 +27,9 @@ public class OwnerId {
public byte[] toHash() { public byte[] toHash() {
return Base58.decode(value); return Base58.decode(value);
} }
@Override
public String toString() {
return value;
}
} }

View file

@ -1,7 +1,7 @@
package info.frostfs.sdk.dto; package info.frostfs.sdk.dto.object;
import info.frostfs.sdk.dto.object.ObjectHeader; import frostfs.refs.Types;
import info.frostfs.sdk.dto.object.ObjectId; import info.frostfs.sdk.dto.response.Signature;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -15,6 +15,7 @@ public class Split {
private ObjectId previous; private ObjectId previous;
private Signature parentSignature; private Signature parentSignature;
private ObjectHeader parentHeader; private ObjectHeader parentHeader;
private Types.Signature parentSignatureGrpc;
public Split() { public Split() {
this(new SplitId()); this(new SplitId());
@ -68,4 +69,12 @@ public class Split {
public List<ObjectId> getChildren() { public List<ObjectId> getChildren() {
return children; return children;
} }
public Types.Signature getParentSignatureGrpc() {
return parentSignatureGrpc;
}
public void setParentSignatureGrpc(Types.Signature parentSignatureGrpc) {
this.parentSignatureGrpc = parentSignatureGrpc;
}
} }

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.dto; package info.frostfs.sdk.dto.object;
import java.util.UUID; import java.util.UUID;
@ -21,8 +21,8 @@ public class SplitId {
this.id = asUuid(binary); this.id = asUuid(binary);
} }
public SplitId(String str) { public SplitId(String string) {
this.id = UUID.fromString(str); this.id = UUID.fromString(string);
} }
@Override @Override

View file

@ -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_MAJOR_VERSION;
import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION; import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION;

View file

@ -1,20 +1,20 @@
package info.frostfs.sdk.dto; package info.frostfs.sdk.dto.response;
import info.frostfs.sdk.enums.StatusCode; import info.frostfs.sdk.enums.StatusCode;
import static info.frostfs.sdk.constants.FieldConst.EMPTY_STRING; import static info.frostfs.sdk.constants.FieldConst.EMPTY_STRING;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
public class Status { public class ResponseStatus {
private StatusCode code; private StatusCode code;
private String message; private String message;
public Status(StatusCode code, String message) { public ResponseStatus(StatusCode code, String message) {
this.code = code; this.code = code;
this.message = isNull(message) ? EMPTY_STRING : message; this.message = isNull(message) ? EMPTY_STRING : message;
} }
public Status(StatusCode code) { public ResponseStatus(StatusCode code) {
this.code = code; this.code = code;
this.message = EMPTY_STRING; this.message = EMPTY_STRING;
} }

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.dto; package info.frostfs.sdk.dto.response;
import info.frostfs.sdk.enums.SignatureScheme; import info.frostfs.sdk.enums.SignatureScheme;

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -4,8 +4,8 @@ import com.google.protobuf.ByteString;
import frostfs.container.Types; import frostfs.container.Types;
import info.frostfs.sdk.dto.container.Container; import info.frostfs.sdk.dto.container.Container;
import info.frostfs.sdk.enums.BasicAcl; 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.PlacementPolicyMapper;
import info.frostfs.sdk.mappers.netmap.VersionMapper;
import static info.frostfs.sdk.UuidExtension.asBytes; import static info.frostfs.sdk.UuidExtension.asBytes;
import static info.frostfs.sdk.UuidExtension.asUuid; import static info.frostfs.sdk.UuidExtension.asUuid;

View file

@ -5,7 +5,6 @@ import frostfs.netmap.Types;
import frostfs.netmap.Types.NodeInfo.Attribute; import frostfs.netmap.Types.NodeInfo.Attribute;
import info.frostfs.sdk.dto.netmap.NodeInfo; import info.frostfs.sdk.dto.netmap.NodeInfo;
import info.frostfs.sdk.enums.NodeState; import info.frostfs.sdk.enums.NodeState;
import info.frostfs.sdk.mappers.VersionMapper;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View file

@ -1,7 +1,7 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.netmap;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.dto.Version; import info.frostfs.sdk.dto.netmap.Version;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;

View file

@ -12,7 +12,7 @@ public class ObjectFilterMapper {
private ObjectFilterMapper() { private ObjectFilterMapper() {
} }
public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter filter) { public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter<?> filter) {
if (isNull(filter)) { if (isNull(filter)) {
return null; return null;
} }
@ -27,7 +27,7 @@ public class ObjectFilterMapper {
return Service.SearchRequest.Body.Filter.newBuilder() return Service.SearchRequest.Body.Filter.newBuilder()
.setMatchType(objectMatchType) .setMatchType(objectMatchType)
.setKey(filter.getKey()) .setKey(filter.getKey())
.setValue(filter.getValue()) .setValue(filter.getSerializedValue())
.build(); .build();
} }
} }

View file

@ -1,27 +1,30 @@
package info.frostfs.sdk.mappers.object; package info.frostfs.sdk.mappers.object;
import com.google.protobuf.ByteString;
import frostfs.object.Types; import frostfs.object.Types;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.dto.object.ObjectAttribute; import info.frostfs.sdk.dto.object.ObjectAttribute;
import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.enums.ObjectType; import info.frostfs.sdk.enums.ObjectType;
import info.frostfs.sdk.mappers.VersionMapper;
import info.frostfs.sdk.mappers.container.ContainerIdMapper; import info.frostfs.sdk.mappers.container.ContainerIdMapper;
import info.frostfs.sdk.mappers.netmap.VersionMapper;
import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.ListUtils;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
public class ObjectHeaderMapper { public class ObjectHeaderMapper {
private static final String ERROR_UNKNOWN_VALUE_TEMPLATE = "Unknown ObjectType. Value: %s."; 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() { private ObjectHeaderMapper() {
} }
public static Types.Header toGrpcMessage(ObjectHeader header) { public static Types.Header toGrpcMessage(ObjectHeader header) {
if (isNull(header)) { if (isNull(header)) {
return null; throw new IllegalArgumentException(ERROR_OBJECT_HEADER_MISSING_ERROR);
} }
var objectType = Types.ObjectType.forNumber(header.getObjectType().value); var objectType = Types.ObjectType.forNumber(header.getObjectType().value);
@ -32,13 +35,23 @@ public class ObjectHeaderMapper {
} }
var head = Types.Header.newBuilder() var head = Types.Header.newBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(header.getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(header.getVersion()))
.setContainerId(ContainerIdMapper.toGrpcMessage(header.getContainerId())) .setContainerId(ContainerIdMapper.toGrpcMessage(header.getContainerId()))
.setObjectType(objectType); .setObjectType(objectType)
.setPayloadLength(header.getPayloadLength());
for (ObjectAttribute objectAttribute : header.getAttributes()) { for (ObjectAttribute objectAttribute : header.getAttributes()) {
head.addAttributes(ObjectAttributeMapper.toGrpcMessage(objectAttribute)); 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(); return head.build();
} }

View file

@ -1,8 +1,8 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.object;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.dto.OwnerId; import info.frostfs.sdk.dto.object.OwnerId;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;

View file

@ -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());
}
}

View file

@ -1,20 +1,20 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.response;
import frostfs.status.Types; import frostfs.status.Types;
import info.frostfs.sdk.dto.Status; import info.frostfs.sdk.dto.response.ResponseStatus;
import info.frostfs.sdk.enums.StatusCode; import info.frostfs.sdk.enums.StatusCode;
import static java.util.Objects.isNull; 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 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)) { if (isNull(status)) {
return new Status(StatusCode.SUCCESS); return new ResponseStatus(StatusCode.SUCCESS);
} }
var statusCode = StatusCode.get(status.getCode()); 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());
} }
} }

View file

@ -1,8 +1,8 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.response;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.dto.Signature; import info.frostfs.sdk.dto.response.Signature;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.session;
import com.google.protobuf.CodedOutputStream; import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;

View file

@ -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));
}
}

View file

@ -1,7 +1,7 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.netmap;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.dto.Version; import info.frostfs.sdk.dto.netmap.Version;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;

View file

@ -18,7 +18,7 @@ public class ObjectFilterMapperTest {
@EnumSource(value = ObjectMatchType.class) @EnumSource(value = ObjectMatchType.class)
void toGrpcMessage_success(ObjectMatchType type) { void toGrpcMessage_success(ObjectMatchType type) {
//Given //Given
var objectFilter = new ObjectFilter(type, "key", "value"); var objectFilter = new ObjectFilter.FilterByAttribute(type, "key", "value");
//When //When
var result = ObjectFilterMapper.toGrpcMessage(objectFilter); var result = ObjectFilterMapper.toGrpcMessage(objectFilter);
@ -40,7 +40,7 @@ public class ObjectFilterMapperTest {
@Test @Test
void toGrpcMessage_notValidScheme() { void toGrpcMessage_notValidScheme() {
//Given //Given
var objectFilter = new ObjectFilter(UNSPECIFIED, "key", "value"); var objectFilter = new ObjectFilter.FilterByAttribute(UNSPECIFIED, "key", "value");
//When + Then //When + Then
try (MockedStatic<Types.MatchType> mockStatic = mockStatic(Types.MatchType.class)) { try (MockedStatic<Types.MatchType> mockStatic = mockStatic(Types.MatchType.class)) {

View file

@ -3,16 +3,17 @@ package info.frostfs.sdk.mappers.object;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import frostfs.object.Types; import frostfs.object.Types;
import info.frostfs.sdk.dto.container.ContainerId; 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.ObjectAttribute;
import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.dto.object.OwnerId;
import info.frostfs.sdk.enums.ObjectType; import info.frostfs.sdk.enums.ObjectType;
import info.frostfs.sdk.mappers.response.MetaHeaderMapper;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.MockedStatic; import org.mockito.MockedStatic;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.mockStatic;
@ -27,8 +28,11 @@ public class ObjectHeaderMapperTest {
var objectHeader = new ObjectHeader( var objectHeader = new ObjectHeader(
containerId, containerId,
type, 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 //When
var result = ObjectHeaderMapper.toGrpcMessage(objectHeader); var result = ObjectHeaderMapper.toGrpcMessage(objectHeader);
@ -52,14 +56,14 @@ public class ObjectHeaderMapperTest {
@Test @Test
void toGrpcMessage_null() { void toGrpcMessage_null() {
//When + Then //When + Then
assertNull(ObjectHeaderMapper.toGrpcMessage(null)); assertThrows(IllegalArgumentException.class, () -> ObjectHeaderMapper.toGrpcMessage(null));
} }
@Test @Test
void toGrpcMessage_notValidScheme() { void toGrpcMessage_notValidScheme() {
//Given //Given
var containerId = new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"); var containerId = new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R");
var objectHeader = new ObjectHeader(containerId, ObjectType.REGULAR, null); var objectHeader = new ObjectHeader(containerId, ObjectType.REGULAR);
//When + Then //When + Then
try (MockedStatic<Types.ObjectType> mockStatic = mockStatic(Types.ObjectType.class)) { try (MockedStatic<Types.ObjectType> mockStatic = mockStatic(Types.ObjectType.class)) {

View file

@ -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 org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;

View file

@ -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));
}
}

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.response;
import frostfs.status.Types; import frostfs.status.Types;
import info.frostfs.sdk.enums.StatusCode; import info.frostfs.sdk.enums.StatusCode;
@ -8,7 +8,7 @@ import org.junit.jupiter.params.provider.EnumSource;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
public class StatusMapperTest { public class ResponseStatusMapperTest {
@ParameterizedTest @ParameterizedTest
@EnumSource(value = StatusCode.class) @EnumSource(value = StatusCode.class)
@ -20,7 +20,7 @@ public class StatusMapperTest {
.build(); .build();
//When //When
var result = StatusMapper.toModel(status); var result = ResponseStatusMapper.toModel(status);
//Then //Then
assertNotNull(result); assertNotNull(result);
@ -31,7 +31,7 @@ public class StatusMapperTest {
@Test @Test
void toModel_null() { void toModel_null() {
//When //When
var result = StatusMapper.toModel(null); var result = ResponseStatusMapper.toModel(null);
//Then //Then
assertNotNull(result); assertNotNull(result);
@ -48,6 +48,6 @@ public class StatusMapperTest {
.build(); .build();
//When + Then //When + Then
assertThrows(IllegalArgumentException.class, () -> StatusMapper.toModel(status)); assertThrows(IllegalArgumentException.class, () -> ResponseStatusMapper.toModel(status));
} }
} }

View file

@ -1,7 +1,7 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.response;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.dto.Signature; import info.frostfs.sdk.dto.response.Signature;
import info.frostfs.sdk.enums.SignatureScheme; import info.frostfs.sdk.enums.SignatureScheme;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.mappers; package info.frostfs.sdk.mappers.session;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import frostfs.session.Types; import frostfs.session.Types;