[#34] Provide input parameters for all grpc methods #35
61 changed files with 1411 additions and 625 deletions
112
README.md
112
README.md
|
@ -21,31 +21,40 @@ neo-go wallet export -w <path_to_your_wallet> -d <address_from_p1>
|
|||
### Container operations
|
||||
|
||||
```java
|
||||
import info.frostfs.sdk.FrostFSClient;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.netmap.PlacementPolicy;
|
||||
import info.frostfs.sdk.dto.netmap.Replica;
|
||||
import info.frostfs.sdk.enums.BasicAcl;
|
||||
import info.frostfs.sdk.jdo.ClientSettings;
|
||||
import info.frostfs.sdk.FrostFSClient;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerCreate;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerDelete;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGet;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGetAll;
|
||||
|
||||
public class ContainerExample {
|
||||
|
||||
public void example() {
|
||||
var callContext = new CallContext();
|
||||
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
|
||||
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
|
||||
|
||||
// Create container
|
||||
var placementPolicy = new PlacementPolicy(new Replica[]{new Replica(1)}, Boolean.TRUE);
|
||||
var containerId = frostFSClient.createContainer(new Container(BasicAcl.PUBLIC_RW, placementPolicy));
|
||||
var placementPolicy = new PlacementPolicy(new Replica[]{new Replica(1)}, true);
|
||||
var prmContainerCreate = new PrmContainerCreate(new Container(BasicAcl.PUBLIC_RW, placementPolicy));
|
||||
var containerId = frostFSClient.createContainer(prmContainerCreate, callContext);
|
||||
|
||||
// Get container
|
||||
var container = frostFSClient.getContainer(containerId);
|
||||
var prmContainerGet = new PrmContainerGet(containerId);
|
||||
var container = frostFSClient.getContainer(prmContainerGet, callContext);
|
||||
|
||||
// List containers
|
||||
var containerIds = frostFSClient.listContainers();
|
||||
var containerIds = frostFSClient.listContainers(new PrmContainerGetAll(), callContext);
|
||||
|
||||
// Delete container
|
||||
frostFSClient.deleteContainer(containerId);
|
||||
var prmContainerDelete = new PrmContainerDelete(containerId);
|
||||
frostFSClient.deleteContainer(prmContainerDelete, callContext);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -53,45 +62,104 @@ public class ContainerExample {
|
|||
### Object operations
|
||||
|
||||
```java
|
||||
import info.frostfs.sdk.dto.object.*;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectAttribute;
|
||||
import info.frostfs.sdk.dto.object.ObjectFilter;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.jdo.PutObjectParameters;
|
||||
import info.frostfs.sdk.FrostFSClient;
|
||||
import info.frostfs.sdk.jdo.ClientSettings;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.object.*;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ObjectExample {
|
||||
|
||||
public void example() {
|
||||
CallContext callContext = new CallContext();
|
||||
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
|
||||
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
|
||||
|
||||
// Put object
|
||||
ObjectId objectId;
|
||||
try (FileInputStream fis = new FileInputStream("cat.jpg")) {
|
||||
var cat = new ObjectHeader(
|
||||
containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")}
|
||||
);
|
||||
try (FileInputStream file = new FileInputStream("/path/to/file/cat.jpg")) {
|
||||
var attribute = new ObjectAttribute("Filename", "cat.jpg");
|
||||
var cat = new ObjectHeader(containerId, ObjectType.REGULAR, attribute);
|
||||
var prmObjectPut = PrmObjectPut.builder().objectHeader(cat).build();
|
||||
var writer = frostFSClient.putObject(prmObjectPut, callContext);
|
||||
|
||||
var params = new PutObjectParameters(cat, fis);
|
||||
objectId = frostFSClient.putObject(params);
|
||||
writer.write(file.readAllBytes());
|
||||
objectId = writer.complete();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Get object
|
||||
var obj = frostFSClient.getObject(containerId, objectId);
|
||||
var prmObjectGet = new PrmObjectGet(containerId, oid);
|
||||
ObjectFrostFS object = frostFSClient.getObject(prmObjectGet, callContext);
|
||||
|
||||
var reader = object.getObjectReader();
|
||||
var chunk = reader.readChunk();
|
||||
var length = chunk.length;
|
||||
byte[] buffer = null;
|
||||
while (length > 0) {
|
||||
buffer = isNull(buffer) ? chunk : ArrayHelper.concat(buffer, chunk);
|
||||
|
||||
chunk = object.getObjectReader().readChunk();
|
||||
length = ArrayUtils.isEmpty(chunk) ? 0 : chunk.length;
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream("/path/to/file/newCat.jpg")) {
|
||||
fos.write(buffer);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
// Get object header
|
||||
var objectHeader = frostFSClient.getObjectHead(containerId, objectId);
|
||||
var prmObjectHeadGet = new PrmObjectHeadGet(containerId, objectId);
|
||||
var objectHeader = frostFSClient.getObjectHead(prmObjectHeadGet, callContext);
|
||||
|
||||
// Search regular objects
|
||||
var objectIds = frostFSClient.searchObjects(containerId, new ObjectFilter.FilterByRootObject());
|
||||
var prmObjectSearch = new PrmObjectSearch(containerId, new ObjectFilter.FilterByRootObject());
|
||||
var objectIds = frostFSClient.searchObjects(prmObjectSearch, callContext);
|
||||
|
||||
// Delete object
|
||||
var prmObjectDelete = new PrmObjectDelete(containerId, objectId);
|
||||
frostFSClient.deleteObject(prmObjectDelete, callContext);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pool init
|
||||
|
||||
```java
|
||||
import info.frostfs.sdk.jdo.ECDsa;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.pool.NodeParameters;
|
||||
import info.frostfs.sdk.jdo.pool.PoolInitParameters;
|
||||
import info.frostfs.sdk.pool.Pool;
|
||||
|
||||
public class PoolExample {
|
||||
|
||||
public static void example() {
|
||||
CallContext callContext = new CallContext();
|
||||
|
||||
//Init
|
||||
var nodeParam1 = new NodeParameters(1, <your_host1>, 1);
|
||||
var nodeParam2 = new NodeParameters(1, <your_host2>, 1);
|
||||
var nodeParam3 = new NodeParameters(1, <your_host3>, 1);
|
||||
var nodeParam4 = new NodeParameters(1, <your_host4>, 1);
|
||||
|
||||
PoolInitParameters initParameters = new PoolInitParameters();
|
||||
initParameters.setKey(new ECDsa(<your_key>));
|
||||
initParameters.setNodeParams(new NodeParameters[]{nodeParam1, nodeParam2, nodeParam3, nodeParam4});
|
||||
|
||||
|
||||
Pool pool = new Pool(initParameters);
|
||||
|
||||
//Dial (Required!)
|
||||
pool.dial(callContext);
|
||||
}
|
||||
}
|
||||
```
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>frostfs-sdk-java</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>client</artifactId>
|
||||
|
@ -21,17 +21,17 @@
|
|||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>cryptography</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>models</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>exceptions</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
|
|
|
@ -2,13 +2,11 @@ package info.frostfs.sdk;
|
|||
|
||||
import frostfs.accounting.Types;
|
||||
import info.frostfs.sdk.dto.chain.Chain;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
|
||||
import info.frostfs.sdk.dto.netmap.NodeInfo;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.dto.object.ObjectFilter;
|
||||
import info.frostfs.sdk.dto.object.ObjectFrostFS;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
|
@ -17,13 +15,24 @@ import info.frostfs.sdk.exceptions.ProcessFrostFSException;
|
|||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.ClientSettings;
|
||||
import info.frostfs.sdk.jdo.NetworkSettings;
|
||||
import info.frostfs.sdk.jdo.PutObjectParameters;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainAdd;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainList;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainRemove;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerCreate;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerDelete;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGet;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGetAll;
|
||||
import info.frostfs.sdk.jdo.parameters.object.*;
|
||||
import info.frostfs.sdk.jdo.parameters.session.PrmSessionCreate;
|
||||
import info.frostfs.sdk.jdo.result.ObjectHeaderResult;
|
||||
import info.frostfs.sdk.pool.SessionCache;
|
||||
import info.frostfs.sdk.pool.WrapperPrm;
|
||||
import info.frostfs.sdk.services.CommonClient;
|
||||
import info.frostfs.sdk.services.impl.*;
|
||||
import info.frostfs.sdk.services.impl.interceptor.Configuration;
|
||||
import info.frostfs.sdk.services.impl.interceptor.MonitoringClientInterceptor;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
|
||||
import info.frostfs.sdk.utils.Validator;
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ClientInterceptors;
|
||||
|
@ -55,8 +64,10 @@ public class FrostFSClient implements CommonClient {
|
|||
: initGrpcChannel(clientSettings);
|
||||
|
||||
Channel interceptChannel = ClientInterceptors.intercept(channel, MONITORING_CLIENT_INTERCEPTOR);
|
||||
ClientEnvironment clientEnvironment =
|
||||
new ClientEnvironment(clientSettings.getKey(), interceptChannel, new Version(), this);
|
||||
ClientEnvironment clientEnvironment = new ClientEnvironment(
|
||||
clientSettings.getKey(), interceptChannel, new Version(), this,
|
||||
new SessionCache(0)
|
||||
);
|
||||
|
||||
Validator.validate(clientEnvironment);
|
||||
|
||||
|
@ -75,7 +86,7 @@ public class FrostFSClient implements CommonClient {
|
|||
|
||||
Channel interceptChannel = ClientInterceptors.intercept(channel, MONITORING_CLIENT_INTERCEPTOR);
|
||||
ClientEnvironment clientEnvironment =
|
||||
new ClientEnvironment(prm.getKey(), interceptChannel, new Version(), this);
|
||||
new ClientEnvironment(prm.getKey(), interceptChannel, new Version(), this, cache);
|
||||
|
||||
Validator.validate(clientEnvironment);
|
||||
|
||||
|
@ -90,7 +101,7 @@ public class FrostFSClient implements CommonClient {
|
|||
}
|
||||
|
||||
private void checkFrostFSVersionSupport(Version version) {
|
||||
var localNodeInfo = netmapClientImpl.getLocalNodeInfo();
|
||||
var localNodeInfo = netmapClientImpl.getLocalNodeInfo(new CallContext());
|
||||
if (!localNodeInfo.getVersion().isSupported(version)) {
|
||||
throw new ProcessFrostFSException(
|
||||
String.format(VERSION_UNSUPPORTED_TEMPLATE, localNodeInfo.getVersion())
|
||||
|
@ -99,92 +110,97 @@ public class FrostFSClient implements CommonClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Container getContainer(ContainerId cid) {
|
||||
return containerClientImpl.getContainer(cid);
|
||||
public Container getContainer(PrmContainerGet args, CallContext ctx) {
|
||||
return containerClientImpl.getContainer(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContainerId> listContainers() {
|
||||
return containerClientImpl.listContainers();
|
||||
public List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx) {
|
||||
return containerClientImpl.listContainers(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainerId createContainer(Container container) {
|
||||
return containerClientImpl.createContainer(container);
|
||||
public ContainerId createContainer(PrmContainerCreate args, CallContext ctx) {
|
||||
return containerClientImpl.createContainer(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContainer(ContainerId cid) {
|
||||
containerClientImpl.deleteContainer(cid);
|
||||
public void deleteContainer(PrmContainerDelete args, CallContext ctx) {
|
||||
containerClientImpl.deleteContainer(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId) {
|
||||
return objectClientImpl.getObjectHead(containerId, objectId);
|
||||
public ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx) {
|
||||
return objectClientImpl.getObjectHead(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId) {
|
||||
return objectClientImpl.getObject(containerId, objectId);
|
||||
public ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx) {
|
||||
return objectClientImpl.getObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putObject(PutObjectParameters parameters) {
|
||||
return objectClientImpl.putObject(parameters);
|
||||
public ObjectWriter putObject(PrmObjectPut args, CallContext ctx) {
|
||||
return objectClientImpl.putObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putSingleObject(ObjectFrostFS objectFrostFS) {
|
||||
return objectClientImpl.putSingleObject(objectFrostFS);
|
||||
public ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx) {
|
||||
return objectClientImpl.putClientCutObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObject(ContainerId containerId, ObjectId objectId) {
|
||||
objectClientImpl.deleteObject(containerId, objectId);
|
||||
public ObjectId putSingleObject(PrmObjectSinglePut args, CallContext ctx) {
|
||||
return objectClientImpl.putSingleObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) {
|
||||
return objectClientImpl.searchObjects(cid, filters);
|
||||
public void deleteObject(PrmObjectDelete args, CallContext ctx) {
|
||||
objectClientImpl.deleteObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] addChain(Chain chain, ChainTarget chainTarget) {
|
||||
return apeManagerClient.addChain(chain, chainTarget);
|
||||
public Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx) {
|
||||
return objectClientImpl.searchObjects(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChain(Chain chain, ChainTarget chainTarget) {
|
||||
apeManagerClient.removeChain(chain, chainTarget);
|
||||
public byte[] addChain(PrmApeChainAdd args, CallContext ctx) {
|
||||
return apeManagerClient.addChain(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Chain> listChains(ChainTarget chainTarget) {
|
||||
return apeManagerClient.listChains(chainTarget);
|
||||
public void removeChain(PrmApeChainRemove args, CallContext ctx) {
|
||||
apeManagerClient.removeChain(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetmapSnapshot getNetmapSnapshot() {
|
||||
return netmapClientImpl.getNetmapSnapshot();
|
||||
public List<Chain> listChains(PrmApeChainList args, CallContext ctx) {
|
||||
return apeManagerClient.listChains(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeInfo getLocalNodeInfo() {
|
||||
return netmapClientImpl.getLocalNodeInfo();
|
||||
public NetmapSnapshot getNetmapSnapshot(CallContext ctx) {
|
||||
return netmapClientImpl.getNetmapSnapshot(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkSettings getNetworkSettings() {
|
||||
return netmapClientImpl.getNetworkSettings();
|
||||
public NodeInfo getLocalNodeInfo(CallContext ctx) {
|
||||
return netmapClientImpl.getLocalNodeInfo(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionToken createSession(long expiration) {
|
||||
return sessionClientImpl.createSession(expiration);
|
||||
public NetworkSettings getNetworkSettings(CallContext ctx) {
|
||||
return netmapClientImpl.getNetworkSettings(ctx);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken createSessionInternal(long expiration) {
|
||||
return sessionClientImpl.createSessionInternal(expiration);
|
||||
@Override
|
||||
public SessionToken createSession(PrmSessionCreate args, CallContext ctx) {
|
||||
return sessionClientImpl.createSession(args, ctx);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken createSessionInternal(PrmSessionCreate args, CallContext ctx) {
|
||||
return sessionClientImpl.createSessionInternal(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -193,12 +209,12 @@ public class FrostFSClient implements CommonClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Types.Decimal getBalance() {
|
||||
return accountingClient.getBalance();
|
||||
public Types.Decimal getBalance(CallContext ctx) {
|
||||
return accountingClient.getBalance(ctx);
|
||||
}
|
||||
|
||||
public String dial() {
|
||||
accountingClient.getBalance();
|
||||
public String dial(CallContext ctx) {
|
||||
accountingClient.getBalance(ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,14 @@ import info.frostfs.sdk.annotations.NotNull;
|
|||
import info.frostfs.sdk.annotations.Validate;
|
||||
import info.frostfs.sdk.dto.netmap.Version;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
import info.frostfs.sdk.pool.SessionCache;
|
||||
import io.grpc.Channel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static info.frostfs.sdk.Helper.getHexString;
|
||||
import static info.frostfs.sdk.pool.Pool.formCacheKey;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
@ -15,35 +20,48 @@ public class ClientEnvironment {
|
|||
|
||||
@NotNull
|
||||
private final OwnerId ownerId;
|
||||
|
||||
@NotNull
|
||||
private final Version version;
|
||||
|
||||
@NotNull
|
||||
@Validate
|
||||
private final ECDsa key;
|
||||
|
||||
@NotNull
|
||||
private final Channel channel;
|
||||
|
||||
@NotNull
|
||||
private final FrostFSClient frostFSClient;
|
||||
|
||||
private String sessionKey;
|
||||
private String address;
|
||||
private NetworkSettings networkSettings;
|
||||
|
||||
public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient) {
|
||||
private SessionCache sessionCache;
|
||||
|
||||
public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient,
|
||||
SessionCache sessionCache) {
|
||||
this.key = new ECDsa(wif);
|
||||
this.ownerId = new OwnerId(key.getPublicKeyByte());
|
||||
this.version = version;
|
||||
this.channel = channel;
|
||||
this.frostFSClient = frostFSClient;
|
||||
this.sessionCache = sessionCache;
|
||||
this.address = channel.authority();
|
||||
}
|
||||
|
||||
public ClientEnvironment(ECDsa key, Channel channel, Version version, FrostFSClient frostFSClient) {
|
||||
public ClientEnvironment(ECDsa key, Channel channel, Version version, FrostFSClient frostFSClient,
|
||||
SessionCache sessionCache) {
|
||||
this.key = key;
|
||||
this.ownerId = new OwnerId(key.getPublicKeyByte());
|
||||
this.version = version;
|
||||
this.channel = channel;
|
||||
this.frostFSClient = frostFSClient;
|
||||
this.sessionCache = sessionCache;
|
||||
}
|
||||
|
||||
public String getSessionKey() {
|
||||
if (StringUtils.isBlank(sessionKey)) {
|
||||
this.sessionKey = formCacheKey(address, getHexString(key.getPublicKeyByte()));
|
||||
}
|
||||
|
||||
return sessionKey;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PutObjectParameters {
|
||||
|
||||
@NotNull
|
||||
private ObjectHeader header;
|
||||
|
||||
@NotNull
|
||||
private InputStream payload;
|
||||
|
||||
private boolean clientCut;
|
||||
private int bufferMaxSize;
|
||||
private byte[] customerBuffer;
|
||||
private SessionToken sessionToken;
|
||||
private int maxObjectSizeCache;
|
||||
private long currentStreamPosition;
|
||||
private long fullLength;
|
||||
|
||||
public PutObjectParameters(ObjectHeader header, InputStream payload, boolean clientCut, int bufferMaxSize) {
|
||||
this.header = header;
|
||||
this.payload = payload;
|
||||
this.clientCut = clientCut;
|
||||
this.bufferMaxSize = bufferMaxSize;
|
||||
}
|
||||
|
||||
public PutObjectParameters(ObjectHeader header, InputStream payload) {
|
||||
this.header = header;
|
||||
this.payload = payload;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package info.frostfs.sdk.jdo.parameters;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static info.frostfs.sdk.constants.AppConst.DEFAULT_GRPC_TIMEOUT;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class CallContext {
|
||||
private final long timeout;
|
||||
|
||||
private final TimeUnit timeUnit;
|
||||
|
||||
public CallContext() {
|
||||
this.timeout = DEFAULT_GRPC_TIMEOUT;
|
||||
this.timeUnit = TimeUnit.SECONDS;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package info.frostfs.sdk.jdo;
|
||||
package info.frostfs.sdk.jdo.parameters;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
@ -8,14 +8,14 @@ import java.time.LocalDateTime;
|
|||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class WaitParameters {
|
||||
public class PrmWait {
|
||||
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() {
|
||||
public PrmWait() {
|
||||
this.timeout = DEFAULT_TIMEOUT;
|
||||
this.pollInterval = DEFAULT_POLL_INTERVAL;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package info.frostfs.sdk.jdo.parameters.ape;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.chain.Chain;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmApeChainAdd {
|
||||
@NotNull
|
||||
private Chain chain;
|
||||
@NotNull
|
||||
private ChainTarget chainTarget;
|
||||
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmApeChainAdd(Chain chain, ChainTarget chainTarget) {
|
||||
this.chain = chain;
|
||||
this.chainTarget = chainTarget;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package info.frostfs.sdk.jdo.parameters.ape;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmApeChainList {
|
||||
@NotNull
|
||||
private ChainTarget chainTarget;
|
||||
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmApeChainList(ChainTarget chainTarget) {
|
||||
this.chainTarget = chainTarget;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package info.frostfs.sdk.jdo.parameters.ape;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.chain.Chain;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmApeChainRemove {
|
||||
@NotNull
|
||||
private Chain chain;
|
||||
@NotNull
|
||||
private ChainTarget chainTarget;
|
||||
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmApeChainRemove(Chain chain, ChainTarget chainTarget) {
|
||||
this.chain = chain;
|
||||
this.chainTarget = chainTarget;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package info.frostfs.sdk.jdo.parameters.container;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.PrmWait;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmContainerCreate implements SessionContext {
|
||||
@NotNull
|
||||
private Container container;
|
||||
|
||||
private PrmWait waitParams;
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmContainerCreate(Container container, PrmWait waitParams) {
|
||||
this.container = container;
|
||||
this.waitParams = waitParams;
|
||||
}
|
||||
|
||||
public PrmContainerCreate(Container container) {
|
||||
this.container = container;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package info.frostfs.sdk.jdo.parameters.container;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.PrmWait;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmContainerDelete implements SessionContext {
|
||||
@NotNull
|
||||
private ContainerId containerId;
|
||||
|
||||
private PrmWait waitParams;
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmContainerDelete(ContainerId containerId, PrmWait waitParams) {
|
||||
this.containerId = containerId;
|
||||
this.waitParams = waitParams;
|
||||
}
|
||||
|
||||
public PrmContainerDelete(ContainerId containerId) {
|
||||
this.containerId = containerId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package info.frostfs.sdk.jdo.parameters.container;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmContainerGet {
|
||||
@NotNull
|
||||
private ContainerId containerId;
|
||||
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmContainerGet(ContainerId containerId) {
|
||||
this.containerId = containerId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package info.frostfs.sdk.jdo.parameters.container;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PrmContainerGetAll {
|
||||
private Map<String, String> xHeaders;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectClientCutPut implements PrmObjectPutBase, SessionContext {
|
||||
@NotNull
|
||||
private final PutObjectContext putObjectContext = new PutObjectContext();
|
||||
@NotNull
|
||||
private ObjectHeader objectHeader;
|
||||
@NotNull
|
||||
private InputStream payload;
|
||||
private int bufferMaxSize;
|
||||
private byte[] customerBuffer;
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectDelete implements SessionContext {
|
||||
@NotNull
|
||||
private ContainerId containerId;
|
||||
@NotNull
|
||||
private ObjectId objectId;
|
||||
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmObjectDelete(ContainerId containerId, ObjectId objectId) {
|
||||
this.containerId = containerId;
|
||||
this.objectId = objectId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectGet implements SessionContext {
|
||||
@NotNull
|
||||
private ContainerId containerId;
|
||||
@NotNull
|
||||
private ObjectId objectId;
|
||||
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmObjectGet(ContainerId containerId, ObjectId objectId) {
|
||||
this.containerId = containerId;
|
||||
this.objectId = objectId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectHeadGet implements SessionContext {
|
||||
@NotNull
|
||||
private ContainerId containerId;
|
||||
@NotNull
|
||||
private ObjectId objectId;
|
||||
|
||||
private boolean raw;
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmObjectHeadGet(ContainerId containerId, ObjectId objectId) {
|
||||
this.containerId = containerId;
|
||||
this.objectId = objectId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectPut implements PrmObjectPutBase, SessionContext {
|
||||
@NotNull
|
||||
private final PutObjectContext putObjectContext = new PutObjectContext();
|
||||
@NotNull
|
||||
private ObjectHeader objectHeader;
|
||||
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmObjectPut(ObjectHeader objectHeader) {
|
||||
this.objectHeader = objectHeader;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface PrmObjectPutBase extends SessionContext {
|
||||
ObjectHeader getObjectHeader();
|
||||
|
||||
Map<String, String> getXHeaders();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectFilter;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectSearch implements SessionContext {
|
||||
@NotNull
|
||||
private ContainerId containerId;
|
||||
@NotNull
|
||||
private ObjectFilter<?>[] filters;
|
||||
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmObjectSearch(ContainerId containerId, ObjectFilter<?>... filters) {
|
||||
this.containerId = containerId;
|
||||
this.filters = filters;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import info.frostfs.sdk.annotations.NotNull;
|
||||
import info.frostfs.sdk.dto.object.ObjectFrostFS;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmObjectSinglePut implements SessionContext {
|
||||
@NotNull
|
||||
private ObjectFrostFS objectFrostFS;
|
||||
|
||||
private SessionToken sessionToken;
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmObjectSinglePut(ObjectFrostFS objectFrostFS) {
|
||||
this.objectFrostFS = objectFrostFS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package info.frostfs.sdk.jdo.parameters.object;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class PutObjectContext {
|
||||
private int maxObjectSizeCache;
|
||||
private long currentStreamPosition;
|
||||
private long fullLength;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package info.frostfs.sdk.jdo.parameters.session;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class PrmSessionCreate {
|
||||
private long expiration; //-1 is max
|
||||
private Map<String, String> xHeaders;
|
||||
|
||||
public PrmSessionCreate(long expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package info.frostfs.sdk.jdo.parameters.session;
|
||||
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
|
||||
public interface SessionContext {
|
||||
SessionToken getSessionToken();
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package info.frostfs.sdk.jdo.result;
|
||||
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.SplitInfo;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
@Setter
|
||||
public class ObjectHeaderResult {
|
||||
private ObjectHeader headerInfo;
|
||||
private SplitInfo splitInfo;
|
||||
}
|
|
@ -4,6 +4,7 @@ import info.frostfs.sdk.FrostFSClient;
|
|||
import info.frostfs.sdk.enums.MethodIndex;
|
||||
import info.frostfs.sdk.exceptions.ResponseFrostFSException;
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.utils.WaitUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
@ -45,12 +46,12 @@ public class ClientWrapper extends ClientStatusMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
public void dial() {
|
||||
public void dial(CallContext ctx) {
|
||||
FrostFSClient client = getClient();
|
||||
if (client == null) {
|
||||
throw new ValidationFrostFSException(POOL_CLIENT_UNHEALTHY);
|
||||
}
|
||||
client.dial();
|
||||
client.dial(ctx);
|
||||
}
|
||||
|
||||
public void handleError(Exception exp) {
|
||||
|
@ -77,9 +78,9 @@ public class ClientWrapper extends ClientStatusMonitor {
|
|||
client.close();
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> restartIfUnhealthy() {
|
||||
public CompletableFuture<Boolean> restartIfUnhealthy(CallContext ctx) {
|
||||
try {
|
||||
client.getLocalNodeInfo();
|
||||
client.getLocalNodeInfo(ctx);
|
||||
return CompletableFuture.completedFuture(false);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
@ -88,15 +89,15 @@ public class ClientWrapper extends ClientStatusMonitor {
|
|||
scheduleGracefulClose();
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(restartClient());
|
||||
return CompletableFuture.completedFuture(restartClient(ctx));
|
||||
}
|
||||
|
||||
private boolean restartClient() {
|
||||
private boolean restartClient(CallContext ctx) {
|
||||
FrostFSClient newClient = null;
|
||||
try {
|
||||
newClient = new FrostFSClient(wrapperPrm, sessionCache);
|
||||
|
||||
var error = newClient.dial();
|
||||
var error = newClient.dial(ctx);
|
||||
if (StringUtils.isNotBlank(error)) {
|
||||
setUnhealthyOnDial();
|
||||
newClient.close();
|
||||
|
@ -113,7 +114,7 @@ public class ClientWrapper extends ClientStatusMonitor {
|
|||
}
|
||||
|
||||
try {
|
||||
client.getLocalNodeInfo();
|
||||
client.getLocalNodeInfo(ctx);
|
||||
} catch (Exception exp) {
|
||||
setUnhealthy();
|
||||
return true;
|
||||
|
|
|
@ -2,12 +2,14 @@ package info.frostfs.sdk.pool;
|
|||
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.dto.chain.Chain;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
|
||||
import info.frostfs.sdk.dto.netmap.NodeInfo;
|
||||
import info.frostfs.sdk.dto.object.*;
|
||||
import info.frostfs.sdk.dto.object.ObjectFrostFS;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.exceptions.FrostFSException;
|
||||
import info.frostfs.sdk.exceptions.SessionExpiredFrostFSException;
|
||||
|
@ -15,10 +17,21 @@ import info.frostfs.sdk.exceptions.SessionNotFoundFrostFSException;
|
|||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.ECDsa;
|
||||
import info.frostfs.sdk.jdo.NetworkSettings;
|
||||
import info.frostfs.sdk.jdo.PutObjectParameters;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainAdd;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainList;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainRemove;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerCreate;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerDelete;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGet;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGetAll;
|
||||
import info.frostfs.sdk.jdo.parameters.object.*;
|
||||
import info.frostfs.sdk.jdo.parameters.session.PrmSessionCreate;
|
||||
import info.frostfs.sdk.jdo.pool.NodeParameters;
|
||||
import info.frostfs.sdk.jdo.pool.PoolInitParameters;
|
||||
import info.frostfs.sdk.jdo.result.ObjectHeaderResult;
|
||||
import info.frostfs.sdk.services.CommonClient;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
|
||||
import info.frostfs.sdk.utils.FrostFSMessages;
|
||||
import info.frostfs.sdk.utils.WaitUtil;
|
||||
import lombok.Getter;
|
||||
|
@ -171,21 +184,21 @@ public class Pool implements CommonClient {
|
|||
}
|
||||
}
|
||||
|
||||
private static SessionToken initSessionForDuration(ClientWrapper cw, long duration) {
|
||||
private static SessionToken initSessionForDuration(CallContext ctx, ClientWrapper cw, long duration) {
|
||||
var client = cw.getClient();
|
||||
NetworkSettings networkInfo = client.getNetworkSettings();
|
||||
NetworkSettings networkInfo = client.getNetworkSettings(ctx);
|
||||
|
||||
long epoch = networkInfo.getEpochDuration();
|
||||
long exp = (Long.MAX_VALUE - epoch < duration) ? Long.MAX_VALUE : (epoch + duration);
|
||||
|
||||
return client.createSession(exp);
|
||||
return client.createSession(new PrmSessionCreate(exp), ctx);
|
||||
}
|
||||
|
||||
private static String formCacheKey(String address, String key) {
|
||||
public static String formCacheKey(String address, String key) {
|
||||
return address + key;
|
||||
}
|
||||
|
||||
public String dial() {
|
||||
public String dial(CallContext ctx) {
|
||||
InnerPool[] inner = new InnerPool[rebalanceParams.getNodesParams().length];
|
||||
boolean atLeastOneHealthy = false;
|
||||
int i = 0;
|
||||
|
@ -198,10 +211,12 @@ public class Pool implements CommonClient {
|
|||
boolean dialed = false;
|
||||
|
||||
try {
|
||||
client.dial();
|
||||
client.dial(ctx);
|
||||
dialed = true;
|
||||
|
||||
SessionToken token = initSessionForDuration(client, rebalanceParams.getSessionExpirationDuration());
|
||||
SessionToken token = initSessionForDuration(
|
||||
ctx, client, rebalanceParams.getSessionExpirationDuration()
|
||||
);
|
||||
String cacheKey = formCacheKey(
|
||||
nodeParams.getAddress().get(j),
|
||||
getHexString(key.getPublicKeyByte())
|
||||
|
@ -236,10 +251,10 @@ public class Pool implements CommonClient {
|
|||
|
||||
this.innerPools = inner;
|
||||
|
||||
NetworkSettings networkSettings = getNetworkSettings();
|
||||
NetworkSettings networkSettings = getNetworkSettings(ctx);
|
||||
|
||||
this.maxObjectSize = networkSettings.getMaxObjectSize();
|
||||
startRebalance();
|
||||
startRebalance(ctx);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -267,7 +282,7 @@ public class Pool implements CommonClient {
|
|||
}
|
||||
}
|
||||
|
||||
public void startRebalance() {
|
||||
public void startRebalance(CallContext ctx) {
|
||||
double[][] buffers = new double[rebalanceParams.getNodesParams().length][];
|
||||
|
||||
for (int i = 0; i < rebalanceParams.getNodesParams().length; i++) {
|
||||
|
@ -276,24 +291,24 @@ public class Pool implements CommonClient {
|
|||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
WaitUtil.sleep(rebalanceParams.getClientRebalanceInterval());
|
||||
updateNodesHealth(buffers);
|
||||
updateNodesHealth(ctx, buffers);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNodesHealth(double[][] buffers) {
|
||||
private void updateNodesHealth(CallContext ctx, double[][] buffers) {
|
||||
CompletableFuture<?>[] tasks = new CompletableFuture<?>[innerPools.length];
|
||||
|
||||
for (int i = 0; i < innerPools.length; i++) {
|
||||
double[] bufferWeights = buffers[i];
|
||||
int finalI = i;
|
||||
tasks[i] = CompletableFuture.runAsync(() -> updateInnerNodesHealth(finalI, bufferWeights));
|
||||
tasks[i] = CompletableFuture.runAsync(() -> updateInnerNodesHealth(ctx, finalI, bufferWeights));
|
||||
}
|
||||
|
||||
CompletableFuture.allOf(tasks).join();
|
||||
}
|
||||
|
||||
private void updateInnerNodesHealth(int poolIndex, double[] bufferWeights) {
|
||||
private void updateInnerNodesHealth(CallContext ctx, int poolIndex, double[] bufferWeights) {
|
||||
if (poolIndex > innerPools.length - 1) {
|
||||
return;
|
||||
}
|
||||
|
@ -311,7 +326,7 @@ public class Pool implements CommonClient {
|
|||
AtomicBoolean changed = new AtomicBoolean(false);
|
||||
|
||||
int finalJ = j;
|
||||
tasks[j] = client.restartIfUnhealthy().handle((unused, throwable) -> {
|
||||
tasks[j] = client.restartIfUnhealthy(ctx).handle((unused, throwable) -> {
|
||||
if (throwable != null) {
|
||||
error.set(throwable.getMessage());
|
||||
bufferWeights[finalJ] = 0;
|
||||
|
@ -398,112 +413,112 @@ public class Pool implements CommonClient {
|
|||
return statistics;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Container getContainer(ContainerId cid) {
|
||||
public Container getContainer(PrmContainerGet args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getContainer(cid);
|
||||
return client.getClient().getContainer(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContainerId> listContainers() {
|
||||
public List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().listContainers();
|
||||
return client.getClient().listContainers(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainerId createContainer(Container container) {
|
||||
public ContainerId createContainer(PrmContainerCreate args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().createContainer(container);
|
||||
return client.getClient().createContainer(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContainer(ContainerId cid) {
|
||||
public void deleteContainer(PrmContainerDelete args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
client.getClient().deleteContainer(cid);
|
||||
client.getClient().deleteContainer(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId) {
|
||||
public ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getObjectHead(containerId, objectId);
|
||||
return client.getClient().getObjectHead(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId) {
|
||||
public ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getObject(containerId, objectId);
|
||||
return client.getClient().getObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putObject(PutObjectParameters parameters) {
|
||||
public ObjectWriter putObject(PrmObjectPut args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().putObject(parameters);
|
||||
return client.getClient().putObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putSingleObject(ObjectFrostFS objectFrostFS) {
|
||||
public ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().putSingleObject(objectFrostFS);
|
||||
return client.getClient().putClientCutObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObject(ContainerId containerId, ObjectId objectId) {
|
||||
public ObjectId putSingleObject(PrmObjectSinglePut args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
client.getClient().deleteObject(containerId, objectId);
|
||||
return client.getClient().putSingleObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) {
|
||||
public void deleteObject(PrmObjectDelete args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().searchObjects(cid, filters);
|
||||
client.getClient().deleteObject(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] addChain(Chain chain, ChainTarget chainTarget) {
|
||||
public Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().addChain(chain, chainTarget);
|
||||
return client.getClient().searchObjects(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChain(Chain chain, ChainTarget chainTarget) {
|
||||
public byte[] addChain(PrmApeChainAdd args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
client.getClient().removeChain(chain, chainTarget);
|
||||
return client.getClient().addChain(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Chain> listChains(ChainTarget chainTarget) {
|
||||
public void removeChain(PrmApeChainRemove args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().listChains(chainTarget);
|
||||
client.getClient().removeChain(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetmapSnapshot getNetmapSnapshot() {
|
||||
public List<Chain> listChains(PrmApeChainList args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getNetmapSnapshot();
|
||||
return client.getClient().listChains(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeInfo getLocalNodeInfo() {
|
||||
public NetmapSnapshot getNetmapSnapshot(CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getLocalNodeInfo();
|
||||
return client.getClient().getNetmapSnapshot(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkSettings getNetworkSettings() {
|
||||
public NodeInfo getLocalNodeInfo(CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getNetworkSettings();
|
||||
return client.getClient().getLocalNodeInfo(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionToken createSession(long expiration) {
|
||||
public NetworkSettings getNetworkSettings(CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().createSession(expiration);
|
||||
return client.getClient().getNetworkSettings(ctx);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken createSessionInternal(long expiration) {
|
||||
@Override
|
||||
public SessionToken createSession(PrmSessionCreate args, CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().createSessionInternal(expiration);
|
||||
return client.getClient().createSession(args, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -513,8 +528,8 @@ public class Pool implements CommonClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public frostfs.accounting.Types.Decimal getBalance() {
|
||||
public frostfs.accounting.Types.Decimal getBalance(CallContext ctx) {
|
||||
ClientWrapper client = connection();
|
||||
return client.getClient().getBalance();
|
||||
return client.getClient().getBalance(ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.frostfs.sdk.pool;
|
||||
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -18,18 +19,8 @@ public class SessionCache {
|
|||
return cache.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean tryGetValue(String key, SessionToken[] value) {
|
||||
if (key == null) {
|
||||
value[0] = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
SessionToken token = cache.get(key);
|
||||
if (token != null) {
|
||||
value[0] = token;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
public SessionToken tryGetValue(String key) {
|
||||
return StringUtils.isBlank(key) ? null : cache.get(key);
|
||||
}
|
||||
|
||||
public void setValue(String key, SessionToken value) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import frostfs.accounting.Types;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
|
||||
public interface AccountingClient {
|
||||
Types.Decimal getBalance();
|
||||
Types.Decimal getBalance(CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import info.frostfs.sdk.dto.chain.Chain;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainAdd;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainList;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainRemove;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ApeManagerClient {
|
||||
byte[] addChain(Chain chain, ChainTarget chainTarget);
|
||||
byte[] addChain(PrmApeChainAdd args, CallContext ctx);
|
||||
|
||||
void removeChain(Chain chain, ChainTarget chainTarget);
|
||||
void removeChain(PrmApeChainRemove args, CallContext ctx);
|
||||
|
||||
List<Chain> listChains(ChainTarget chainTarget);
|
||||
List<Chain> listChains(PrmApeChainList args, CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -2,15 +2,20 @@ package info.frostfs.sdk.services;
|
|||
|
||||
import info.frostfs.sdk.dto.container.Container;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerCreate;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerDelete;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGet;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGetAll;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ContainerClient {
|
||||
Container getContainer(ContainerId cid);
|
||||
Container getContainer(PrmContainerGet args, CallContext ctx);
|
||||
|
||||
List<ContainerId> listContainers();
|
||||
List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx);
|
||||
|
||||
ContainerId createContainer(Container container);
|
||||
ContainerId createContainer(PrmContainerCreate args, CallContext ctx);
|
||||
|
||||
void deleteContainer(ContainerId cid);
|
||||
void deleteContainer(PrmContainerDelete args, CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,12 @@ package info.frostfs.sdk.services;
|
|||
import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
|
||||
import info.frostfs.sdk.dto.netmap.NodeInfo;
|
||||
import info.frostfs.sdk.jdo.NetworkSettings;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
|
||||
public interface NetmapClient {
|
||||
NetmapSnapshot getNetmapSnapshot();
|
||||
NetmapSnapshot getNetmapSnapshot(CallContext ctx);
|
||||
|
||||
NodeInfo getLocalNodeInfo();
|
||||
NodeInfo getLocalNodeInfo(CallContext ctx);
|
||||
|
||||
NetworkSettings getNetworkSettings();
|
||||
NetworkSettings getNetworkSettings(CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.ObjectFilter;
|
||||
import info.frostfs.sdk.dto.object.ObjectFrostFS;
|
||||
import info.frostfs.sdk.dto.object.ObjectHeader;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.jdo.PutObjectParameters;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.object.*;
|
||||
import info.frostfs.sdk.jdo.result.ObjectHeaderResult;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
|
||||
|
||||
public interface ObjectClient {
|
||||
ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId);
|
||||
ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx);
|
||||
|
||||
ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId);
|
||||
ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx);
|
||||
|
||||
ObjectId putObject(PutObjectParameters parameters);
|
||||
ObjectWriter putObject(PrmObjectPut args, CallContext ctx);
|
||||
|
||||
ObjectId putSingleObject(ObjectFrostFS objectFrostFS);
|
||||
ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx);
|
||||
|
||||
void deleteObject(ContainerId containerId, ObjectId objectId);
|
||||
ObjectId putSingleObject(PrmObjectSinglePut args, CallContext ctx);
|
||||
|
||||
Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters);
|
||||
void deleteObject(PrmObjectDelete args, CallContext ctx);
|
||||
|
||||
Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.session.PrmSessionCreate;
|
||||
|
||||
public interface SessionClient {
|
||||
SessionToken createSession(long expiration);
|
||||
SessionToken createSession(PrmSessionCreate args, CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package info.frostfs.sdk.services;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
|
||||
public interface SessionTools {
|
||||
Types.SessionToken getOrCreateSession(SessionToken token, ClientEnvironment env);
|
||||
SessionToken getOrCreateSession(ClientEnvironment env, CallContext ctx);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import frostfs.accounting.AccountingServiceGrpc;
|
|||
import frostfs.accounting.Service;
|
||||
import frostfs.accounting.Types;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.mappers.object.OwnerIdMapper;
|
||||
import info.frostfs.sdk.services.AccountingClient;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
|
@ -11,7 +12,7 @@ import info.frostfs.sdk.tools.RequestConstructor;
|
|||
import info.frostfs.sdk.tools.RequestSigner;
|
||||
import info.frostfs.sdk.tools.Verifier;
|
||||
|
||||
import java.util.Map;
|
||||
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
|
||||
|
||||
public class AccountingClientImpl extends ContextAccessor implements AccountingClient {
|
||||
private final AccountingServiceGrpc.AccountingServiceBlockingStub serviceBlockingStub;
|
||||
|
@ -22,23 +23,24 @@ public class AccountingClientImpl extends ContextAccessor implements AccountingC
|
|||
}
|
||||
|
||||
@Override
|
||||
public Types.Decimal getBalance() {
|
||||
var request = createGetRequest(null);
|
||||
public Types.Decimal getBalance(CallContext ctx) {
|
||||
var request = createGetRequest();
|
||||
|
||||
var response = serviceBlockingStub.balance(request);
|
||||
var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.balance(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
return response.getBody().getBalance();
|
||||
}
|
||||
|
||||
private Service.BalanceRequest createGetRequest(Map<String, String> xHeaders) {
|
||||
private Service.BalanceRequest createGetRequest() {
|
||||
var body = Service.BalanceRequest.Body.newBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.build();
|
||||
var request = Service.BalanceRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
|
|
|
@ -5,9 +5,11 @@ import frostfs.ape.Types;
|
|||
import frostfs.apemanager.APEManagerServiceGrpc;
|
||||
import frostfs.apemanager.Service;
|
||||
import info.frostfs.sdk.dto.chain.Chain;
|
||||
import info.frostfs.sdk.dto.chain.ChainTarget;
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainAdd;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainList;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainRemove;
|
||||
import info.frostfs.sdk.mappers.chain.ChainMapper;
|
||||
import info.frostfs.sdk.mappers.chain.ChainTargetMapper;
|
||||
import info.frostfs.sdk.services.ApeManagerClient;
|
||||
|
@ -17,10 +19,9 @@ import info.frostfs.sdk.tools.RequestSigner;
|
|||
import info.frostfs.sdk.tools.Verifier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static info.frostfs.sdk.constants.ErrorConst.*;
|
||||
import static java.util.Objects.isNull;
|
||||
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
|
||||
import static info.frostfs.sdk.utils.Validator.validate;
|
||||
|
||||
public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerClient {
|
||||
private final APEManagerServiceGrpc.APEManagerServiceBlockingStub apeManagerServiceClient;
|
||||
|
@ -31,19 +32,13 @@ public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerC
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] addChain(Chain chain, ChainTarget chainTarget) {
|
||||
if (isNull(chain) || isNull(chainTarget)) {
|
||||
throw new ValidationFrostFSException(
|
||||
String.format(
|
||||
PARAMS_ARE_MISSING_TEMPLATE,
|
||||
String.join(FIELDS_DELIMITER_COMMA, Chain.class.getName(), ChainTarget.class.getName())
|
||||
)
|
||||
);
|
||||
}
|
||||
public byte[] addChain(PrmApeChainAdd args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var request = createAddChainRequest(chain, chainTarget, null);
|
||||
var request = createAddChainRequest(args);
|
||||
|
||||
var response = apeManagerServiceClient.addChain(request);
|
||||
var service = deadLineAfter(apeManagerServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.addChain(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
|
@ -51,82 +46,70 @@ public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerC
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeChain(Chain chain, ChainTarget chainTarget) {
|
||||
if (isNull(chain) || isNull(chainTarget)) {
|
||||
throw new ValidationFrostFSException(
|
||||
String.format(
|
||||
PARAMS_ARE_MISSING_TEMPLATE,
|
||||
String.join(FIELDS_DELIMITER_COMMA, Chain.class.getName(), ChainTarget.class.getName())
|
||||
)
|
||||
);
|
||||
}
|
||||
public void removeChain(PrmApeChainRemove args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var request = createRemoveChainRequest(chain, chainTarget, null);
|
||||
var request = createRemoveChainRequest(args);
|
||||
|
||||
var response = apeManagerServiceClient.removeChain(request);
|
||||
var service = deadLineAfter(apeManagerServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.removeChain(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Chain> listChains(ChainTarget chainTarget) {
|
||||
if (isNull(chainTarget)) {
|
||||
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, ChainTarget.class.getName()));
|
||||
}
|
||||
public List<Chain> listChains(PrmApeChainList args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var request = createListChainsRequest(chainTarget, null);
|
||||
var request = createListChainsRequest(args);
|
||||
|
||||
var response = apeManagerServiceClient.listChains(request);
|
||||
var service = deadLineAfter(apeManagerServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.listChains(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return ChainMapper.toModels(response.getBody().getChainsList());
|
||||
}
|
||||
|
||||
private Service.AddChainRequest createAddChainRequest(Chain chain,
|
||||
ChainTarget chainTarget,
|
||||
Map<String, String> xHeaders) {
|
||||
private Service.AddChainRequest createAddChainRequest(PrmApeChainAdd args) {
|
||||
var chainGrpc = Types.Chain.newBuilder()
|
||||
.setRaw(ByteString.copyFrom(chain.getRaw()))
|
||||
.setRaw(ByteString.copyFrom(args.getChain().getRaw()))
|
||||
.build();
|
||||
var body = Service.AddChainRequest.Body.newBuilder()
|
||||
.setChain(chainGrpc)
|
||||
.setTarget(ChainTargetMapper.toGrpcMessage(chainTarget))
|
||||
.setTarget(ChainTargetMapper.toGrpcMessage(args.getChainTarget()))
|
||||
.build();
|
||||
var request = Service.AddChainRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders());
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.RemoveChainRequest createRemoveChainRequest(Chain chain,
|
||||
ChainTarget chainTarget,
|
||||
Map<String, String> xHeaders) {
|
||||
private Service.RemoveChainRequest createRemoveChainRequest(PrmApeChainRemove args) {
|
||||
var body = Service.RemoveChainRequest.Body.newBuilder()
|
||||
.setChainId(ByteString.copyFrom(chain.getRaw()))
|
||||
.setTarget(ChainTargetMapper.toGrpcMessage(chainTarget))
|
||||
.setChainId(ByteString.copyFrom(args.getChain().getRaw()))
|
||||
.setTarget(ChainTargetMapper.toGrpcMessage(args.getChainTarget()))
|
||||
.build();
|
||||
var request = Service.RemoveChainRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders());
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.ListChainsRequest createListChainsRequest(ChainTarget chainTarget,
|
||||
Map<String, String> xHeaders) {
|
||||
private Service.ListChainsRequest createListChainsRequest(PrmApeChainList args) {
|
||||
var body = Service.ListChainsRequest.Body.newBuilder()
|
||||
.setTarget(ChainTargetMapper.toGrpcMessage(chainTarget))
|
||||
.setTarget(ChainTargetMapper.toGrpcMessage(args.getChainTarget()))
|
||||
.build();
|
||||
var request = Service.ListChainsRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders());
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
|
|
|
@ -10,9 +10,14 @@ import info.frostfs.sdk.enums.StatusCode;
|
|||
import info.frostfs.sdk.enums.WaitExpects;
|
||||
import info.frostfs.sdk.exceptions.ResponseFrostFSException;
|
||||
import info.frostfs.sdk.exceptions.TimeoutFrostFSException;
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.WaitParameters;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.PrmWait;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerCreate;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerDelete;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGet;
|
||||
import info.frostfs.sdk.jdo.parameters.container.PrmContainerGetAll;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import info.frostfs.sdk.mappers.container.ContainerIdMapper;
|
||||
import info.frostfs.sdk.mappers.container.ContainerMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.VersionMapper;
|
||||
|
@ -29,8 +34,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static info.frostfs.sdk.constants.ErrorConst.PARAM_IS_MISSING_TEMPLATE;
|
||||
import static info.frostfs.sdk.constants.AttributeConst.DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE;
|
||||
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
|
||||
import static info.frostfs.sdk.utils.Validator.validate;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class ContainerClientImpl extends ContextAccessor implements ContainerClient {
|
||||
private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;
|
||||
|
@ -42,29 +50,33 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
this.sessionTools = new SessionToolsImpl(clientEnvironment);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) {
|
||||
return sessionTools.getOrCreateSession(sessionToken, getContext());
|
||||
public SessionToken getOrCreateSession(SessionContext sessionContext, CallContext ctx) {
|
||||
return isNull(sessionContext.getSessionToken())
|
||||
? sessionTools.getOrCreateSession(getContext(), ctx)
|
||||
: sessionContext.getSessionToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container getContainer(ContainerId cid) {
|
||||
if (isNull(cid)) {
|
||||
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, ContainerId.class.getName()));
|
||||
}
|
||||
public Container getContainer(PrmContainerGet args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var request = createGetRequest(ContainerIdMapper.toGrpcMessage(cid), null);
|
||||
var request = createGetRequest(args);
|
||||
|
||||
var response = serviceBlockingStub.get(request);
|
||||
var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.get(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
return ContainerMapper.toModel(response.getBody().getContainer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContainerId> listContainers() {
|
||||
var request = createListRequest(null);
|
||||
public List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var response = serviceBlockingStub.list(request);
|
||||
var request = createListRequest(args);
|
||||
|
||||
var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.list(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
|
@ -74,43 +86,39 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
}
|
||||
|
||||
@Override
|
||||
public ContainerId createContainer(Container container) {
|
||||
if (isNull(container)) {
|
||||
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, Container.class.getName()));
|
||||
}
|
||||
public ContainerId createContainer(PrmContainerCreate args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var grpcContainer = ContainerMapper.toGrpcMessage(container);
|
||||
var request = createPutRequest(grpcContainer, null);
|
||||
var request = createPutRequest(args, ctx);
|
||||
|
||||
var response = serviceBlockingStub.put(request);
|
||||
var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.put(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
waitForContainer(WaitExpects.EXISTS, response.getBody().getContainerId(), null);
|
||||
waitForContainer(WaitExpects.EXISTS, response.getBody().getContainerId(), args.getWaitParams());
|
||||
|
||||
return new ContainerId(response.getBody().getContainerId().getValue().toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContainer(ContainerId cid) {
|
||||
if (isNull(cid)) {
|
||||
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, ContainerId.class.getName()));
|
||||
}
|
||||
public void deleteContainer(PrmContainerDelete args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid);
|
||||
var request = createDeleteRequest(grpcContainerId, null);
|
||||
var request = createDeleteRequest(args, ctx);
|
||||
|
||||
var response = serviceBlockingStub.delete(request);
|
||||
var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.delete(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
waitForContainer(WaitExpects.REMOVED, request.getBody().getContainerId(), null);
|
||||
waitForContainer(WaitExpects.REMOVED, request.getBody().getContainerId(), args.getWaitParams());
|
||||
}
|
||||
|
||||
private void waitForContainer(WaitExpects expect, Types.ContainerID id, WaitParameters waitParams) {
|
||||
var request = createGetRequest(id, null);
|
||||
private void waitForContainer(WaitExpects expect, Types.ContainerID cid, PrmWait waitParams) {
|
||||
var request = createGetRequest(cid, null);
|
||||
|
||||
waitParams = isNull(waitParams) ? new WaitParameters() : waitParams;
|
||||
waitParams = isNull(waitParams) ? new PrmWait() : waitParams;
|
||||
var deadLine = waitParams.getDeadline();
|
||||
|
||||
while (true) {
|
||||
|
@ -145,9 +153,12 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
}
|
||||
}
|
||||
|
||||
private Service.GetRequest createGetRequest(PrmContainerGet args) {
|
||||
var cid = ContainerIdMapper.toGrpcMessage(args.getContainerId());
|
||||
return createGetRequest(cid, args.getXHeaders());
|
||||
}
|
||||
|
||||
private Service.GetRequest createGetRequest(Types.ContainerID cid,
|
||||
Map<String, String> xHeaders) {
|
||||
private Service.GetRequest createGetRequest(Types.ContainerID cid, Map<String, String> xHeaders) {
|
||||
var body = Service.GetRequest.Body.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.build();
|
||||
|
@ -160,22 +171,22 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
return request.build();
|
||||
}
|
||||
|
||||
private Service.ListRequest createListRequest(Map<String, String> xHeaders) {
|
||||
private Service.ListRequest createListRequest(PrmContainerGetAll args) {
|
||||
var body = Service.ListRequest.Body.newBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.build();
|
||||
var request = Service.ListRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders());
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.PutRequest createPutRequest(frostfs.container.Types.Container container,
|
||||
Map<String, String> xHeaders) {
|
||||
container = container.toBuilder()
|
||||
private Service.PutRequest createPutRequest(PrmContainerCreate args, CallContext ctx) {
|
||||
syncContainerWithNetwork(args.getContainer(), ctx);
|
||||
var container = ContainerMapper.toGrpcMessage(args.getContainer()).toBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
|
||||
.build();
|
||||
|
@ -187,9 +198,8 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
var request = Service.PutRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createContainerTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createContainerTokenContext(
|
||||
sessionToken,
|
||||
null,
|
||||
frostfs.session.Types.ContainerSessionContext.Verb.PUT,
|
||||
|
@ -197,14 +207,15 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.DeleteRequest createDeleteRequest(Types.ContainerID cid,
|
||||
Map<String, String> xHeaders) {
|
||||
private Service.DeleteRequest createDeleteRequest(PrmContainerDelete args, CallContext ctx) {
|
||||
var cid = ContainerIdMapper.toGrpcMessage(args.getContainerId());
|
||||
|
||||
var body = Service.DeleteRequest.Body.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), cid.getValue()))
|
||||
|
@ -212,9 +223,8 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
var request = Service.DeleteRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createContainerTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createContainerTokenContext(
|
||||
sessionToken,
|
||||
null,
|
||||
frostfs.session.Types.ContainerSessionContext.Verb.DELETE,
|
||||
|
@ -222,9 +232,18 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
|
|||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, xHeaders, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
RequestSigner.sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private void syncContainerWithNetwork(Container container, CallContext callContext) {
|
||||
var settings = getContext().getFrostFSClient().getNetworkSettings(callContext);
|
||||
if (nonNull(settings.getHomomorphicHashingDisabled()) && settings.getHomomorphicHashingDisabled()) {
|
||||
container.getAttributes().put(DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE, Boolean.TRUE.toString());
|
||||
} else {
|
||||
container.getAttributes().remove(DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE, Boolean.TRUE.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
|
|||
import info.frostfs.sdk.dto.netmap.NodeInfo;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.NetworkSettings;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.mappers.netmap.NetmapSnapshotMapper;
|
||||
import info.frostfs.sdk.mappers.netmap.NodeInfoMapper;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
|
@ -17,6 +18,7 @@ import info.frostfs.sdk.tools.Verifier;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static info.frostfs.sdk.tools.RequestSigner.sign;
|
||||
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
||||
|
@ -94,12 +96,12 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NetworkSettings getNetworkSettings() {
|
||||
public NetworkSettings getNetworkSettings(CallContext ctx) {
|
||||
if (nonNull(getContext().getNetworkSettings())) {
|
||||
return getContext().getNetworkSettings();
|
||||
}
|
||||
|
||||
var info = getNetworkInfo();
|
||||
var info = getNetworkInfo(ctx);
|
||||
|
||||
var settings = new NetworkSettings();
|
||||
|
||||
|
@ -113,25 +115,28 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NodeInfo getLocalNodeInfo() {
|
||||
public NodeInfo getLocalNodeInfo(CallContext ctx) {
|
||||
var request = Service.LocalNodeInfoRequest.newBuilder();
|
||||
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = netmapServiceClient.localNodeInfo(request.build());
|
||||
var service = deadLineAfter(netmapServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.localNodeInfo(request.build());
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return NodeInfoMapper.toModel(response.getBody());
|
||||
}
|
||||
|
||||
public Service.NetworkInfoResponse getNetworkInfo() {
|
||||
public Service.NetworkInfoResponse getNetworkInfo(CallContext ctx) {
|
||||
var request = Service.NetworkInfoRequest.newBuilder();
|
||||
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = netmapServiceClient.networkInfo(request.build());
|
||||
var service = deadLineAfter(netmapServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.networkInfo(request.build());
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
|
@ -139,13 +144,14 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NetmapSnapshot getNetmapSnapshot() {
|
||||
public NetmapSnapshot getNetmapSnapshot(CallContext ctx) {
|
||||
var request = Service.NetmapSnapshotRequest.newBuilder();
|
||||
|
||||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
var response = netmapServiceClient.netmapSnapshot(request.build());
|
||||
var service = deadLineAfter(netmapServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.netmapSnapshot(request.build());
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
|
|
|
@ -6,29 +6,26 @@ import frostfs.object.ObjectServiceGrpc;
|
|||
import frostfs.object.Service;
|
||||
import frostfs.refs.Types;
|
||||
import info.frostfs.sdk.constants.AppConst;
|
||||
import info.frostfs.sdk.dto.container.ContainerId;
|
||||
import info.frostfs.sdk.dto.object.*;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.enums.ObjectType;
|
||||
import info.frostfs.sdk.exceptions.ProcessFrostFSException;
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.PutObjectParameters;
|
||||
import info.frostfs.sdk.jdo.PutObjectResult;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.object.*;
|
||||
import info.frostfs.sdk.jdo.parameters.session.SessionContext;
|
||||
import info.frostfs.sdk.jdo.result.ObjectHeaderResult;
|
||||
import info.frostfs.sdk.mappers.container.ContainerIdMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectFilterMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectFrostFSMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectHeaderMapper;
|
||||
import info.frostfs.sdk.mappers.object.ObjectIdMapper;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import info.frostfs.sdk.mappers.object.*;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.services.ObjectClient;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectReaderImpl;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectStreamer;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
|
||||
import info.frostfs.sdk.services.impl.rwhelper.SearchReader;
|
||||
import info.frostfs.sdk.tools.RequestConstructor;
|
||||
import info.frostfs.sdk.tools.Verifier;
|
||||
import info.frostfs.sdk.utils.Validator;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -37,9 +34,12 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import static info.frostfs.sdk.Helper.getSha256;
|
||||
import static info.frostfs.sdk.constants.ErrorConst.*;
|
||||
import static info.frostfs.sdk.constants.ErrorConst.PROTO_MESSAGE_IS_EMPTY_TEMPLATE;
|
||||
import static info.frostfs.sdk.tools.RequestSigner.sign;
|
||||
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
|
||||
import static info.frostfs.sdk.utils.Validator.validate;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
||||
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
|
||||
|
@ -55,87 +55,153 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
this.sessionTools = new SessionToolsImpl(clientEnvironment);
|
||||
}
|
||||
|
||||
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) {
|
||||
return sessionTools.getOrCreateSession(sessionToken, getContext());
|
||||
public SessionToken getOrCreateSession(SessionContext sessionContext, CallContext ctx) {
|
||||
return isNull(sessionContext.getSessionToken())
|
||||
? sessionTools.getOrCreateSession(getContext(), ctx)
|
||||
: sessionContext.getSessionToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) {
|
||||
if (isNull(cid) || isNull(oid)) {
|
||||
throw new ValidationFrostFSException(
|
||||
String.format(
|
||||
PARAMS_ARE_MISSING_TEMPLATE,
|
||||
String.join(FIELDS_DELIMITER_COMMA, ContainerId.class.getName(), ObjectId.class.getName())
|
||||
)
|
||||
);
|
||||
}
|
||||
public ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var request = createHeadRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
|
||||
var request = createHeadRequest(args, ctx);
|
||||
|
||||
var response = objectServiceBlockingClient.head(request);
|
||||
var service = deadLineAfter(objectServiceBlockingClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.head(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return ObjectHeaderMapper.toModel(response.getBody().getHeader().getHeader());
|
||||
return ObjectHeaderResult.builder()
|
||||
.headerInfo(ObjectHeaderMapper.toModel(response.getBody().getHeader().getHeader()))
|
||||
.splitInfo(SplitInfoMapper.toModel(response.getBody().getSplitInfo()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectFrostFS getObject(ContainerId cid, ObjectId oid) {
|
||||
var request = createGetRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
|
||||
public ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
return getObject(request);
|
||||
var request = createGetRequest(args, ctx);
|
||||
|
||||
return getObject(request, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteObject(ContainerId cid, ObjectId oid) {
|
||||
var request = createDeleteRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid));
|
||||
public void deleteObject(PrmObjectDelete args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var response = objectServiceBlockingClient.delete(request);
|
||||
var request = createDeleteRequest(args, ctx);
|
||||
|
||||
var service = deadLineAfter(objectServiceBlockingClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.delete(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) {
|
||||
var request = createSearchRequest(ContainerIdMapper.toGrpcMessage(cid), filters);
|
||||
public Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var objectsIds = searchObjects(request);
|
||||
var request = createSearchRequest(args, ctx);
|
||||
|
||||
var objectsIds = searchObjects(request, ctx);
|
||||
|
||||
return Iterables.transform(objectsIds, input -> new ObjectId(input.getValue().toByteArray()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putObject(PutObjectParameters parameters) {
|
||||
Validator.validate(parameters);
|
||||
public ObjectWriter putObject(PrmObjectPut args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
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();
|
||||
return new ObjectWriter(getContext(), args, getUploadStream(args, ctx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putSingleObject(ObjectFrostFS modelObject) {
|
||||
var grpcObject = objectToolsImpl.createObject(modelObject);
|
||||
public ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx) {
|
||||
validate(args);
|
||||
|
||||
var request = createPutSingleRequest(grpcObject);
|
||||
var header = args.getObjectHeader();
|
||||
var fullLength = header.getPayloadLength() == 0 ? getStreamSize(args.getPayload()) : header.getPayloadLength();
|
||||
args.getPutObjectContext().setFullLength(fullLength);
|
||||
|
||||
var response = objectServiceBlockingClient.putSingle(request);
|
||||
if (args.getPutObjectContext().getMaxObjectSizeCache() == 0) {
|
||||
var networkSettings = getContext().getFrostFSClient().getNetworkSettings(ctx);
|
||||
args.getPutObjectContext().setMaxObjectSizeCache(networkSettings.getMaxObjectSize().intValue());
|
||||
}
|
||||
|
||||
var restBytes = fullLength - args.getPutObjectContext().getCurrentStreamPosition();
|
||||
var objectSize = restBytes > 0
|
||||
? Math.min(args.getPutObjectContext().getMaxObjectSizeCache(), restBytes)
|
||||
: args.getPutObjectContext().getMaxObjectSizeCache();
|
||||
|
||||
//define collection capacity
|
||||
var restPart = (restBytes % objectSize) > 0 ? 1 : 0;
|
||||
var objectsCount = fullLength > 0 ? (int) (restBytes / objectSize) + restPart : 0;
|
||||
|
||||
List<ObjectId> sentObjectIds = new ArrayList<>(objectsCount);
|
||||
|
||||
// keep attributes for the large object
|
||||
var attributes = args.getObjectHeader().getAttributes();
|
||||
|
||||
Split split = new Split();
|
||||
args.getObjectHeader().setAttributes(new ArrayList<>());
|
||||
|
||||
// send all parts except the last one as separate Objects
|
||||
while (restBytes > (long) args.getPutObjectContext().getMaxObjectSizeCache()) {
|
||||
var previous = CollectionUtils.isNotEmpty(sentObjectIds)
|
||||
? sentObjectIds.get(sentObjectIds.size() - 1)
|
||||
: null;
|
||||
split.setPrevious(previous);
|
||||
args.getObjectHeader().setSplit(split);
|
||||
|
||||
var result = putMultipartStreamObject(args, ctx);
|
||||
|
||||
sentObjectIds.add(result.getObjectId());
|
||||
|
||||
restBytes -= result.getObjectSize();
|
||||
}
|
||||
|
||||
// send the last part and create linkObject
|
||||
if (CollectionUtils.isNotEmpty(sentObjectIds)) {
|
||||
var largeObjectHeader =
|
||||
new ObjectHeader(header.getContainerId(), ObjectType.REGULAR, attributes, fullLength, null);
|
||||
|
||||
split.setParentHeader(largeObjectHeader);
|
||||
|
||||
var result = putMultipartStreamObject(args, ctx);
|
||||
|
||||
sentObjectIds.add(result.getObjectId());
|
||||
|
||||
var linkObject = new LinkObject(header.getContainerId(), split.getSplitId(), largeObjectHeader);
|
||||
linkObject.addChildren(sentObjectIds);
|
||||
|
||||
putSingleObject(new PrmObjectSinglePut(linkObject), ctx);
|
||||
|
||||
return split.getParent();
|
||||
}
|
||||
|
||||
// We are here if the payload is placed to one Object. It means no cut action, just simple PUT.
|
||||
var singlePartResult = putMultipartStreamObject(args, ctx);
|
||||
|
||||
return singlePartResult.getObjectId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId putSingleObject(PrmObjectSinglePut args, CallContext ctx) {
|
||||
var grpcObject = objectToolsImpl.createObject(args.getObjectFrostFS());
|
||||
var request = createPutSingleRequest(grpcObject, args, ctx);
|
||||
|
||||
var service = deadLineAfter(objectServiceBlockingClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.putSingle(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
return new ObjectId(grpcObject.getObjectId().getValue().toByteArray());
|
||||
}
|
||||
|
||||
private ObjectFrostFS getObject(Service.GetRequest request) {
|
||||
var reader = getObjectInit(request);
|
||||
private ObjectFrostFS getObject(Service.GetRequest request, CallContext ctx) {
|
||||
var reader = getObjectInit(request, ctx);
|
||||
|
||||
var grpcObject = reader.readHeader();
|
||||
var modelObject = ObjectFrostFSMapper.toModel(grpcObject);
|
||||
|
@ -145,39 +211,41 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
return modelObject;
|
||||
}
|
||||
|
||||
private ObjectReaderImpl getObjectInit(Service.GetRequest initRequest) {
|
||||
private ObjectReaderImpl getObjectInit(Service.GetRequest initRequest, CallContext ctx) {
|
||||
if (initRequest.getSerializedSize() == 0) {
|
||||
throw new ProcessFrostFSException(
|
||||
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, initRequest.getClass().getName())
|
||||
);
|
||||
}
|
||||
|
||||
return new ObjectReaderImpl(objectServiceBlockingClient.get(initRequest));
|
||||
var service = deadLineAfter(objectServiceBlockingClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
return new ObjectReaderImpl(service.get(initRequest));
|
||||
}
|
||||
|
||||
private PutObjectResult putStreamObject(PutObjectParameters parameters) {
|
||||
var chunkSize = parameters.getBufferMaxSize() > 0 ? parameters.getBufferMaxSize() : AppConst.OBJECT_CHUNK_SIZE;
|
||||
private PutObjectResult putMultipartStreamObject(PrmObjectClientCutPut args, CallContext ctx) {
|
||||
var chunkSize = args.getBufferMaxSize() > 0 ? args.getBufferMaxSize() : AppConst.OBJECT_CHUNK_SIZE;
|
||||
|
||||
var restBytes = parameters.getFullLength() - parameters.getCurrentStreamPosition();
|
||||
var restBytes =
|
||||
args.getPutObjectContext().getFullLength() - args.getPutObjectContext().getCurrentStreamPosition();
|
||||
|
||||
chunkSize = (int) Math.min(restBytes, chunkSize);
|
||||
|
||||
byte[] chunkBuffer = parameters.getCustomerBuffer() != null
|
||||
? parameters.getCustomerBuffer()
|
||||
byte[] chunkBuffer = args.getCustomerBuffer() != null
|
||||
? args.getCustomerBuffer()
|
||||
: new byte[chunkSize];//todo change to pool
|
||||
|
||||
var sentBytes = 0;
|
||||
|
||||
// 0 means no limit from client, so server side cut is performed
|
||||
var objectLimitSize = parameters.isClientCut() ? parameters.getMaxObjectSizeCache() : 0;
|
||||
var objectLimitSize = args.getPutObjectContext().getMaxObjectSizeCache();
|
||||
|
||||
var stream = getUploadStream(parameters);
|
||||
var stream = getUploadStream(args, ctx);
|
||||
|
||||
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 bytesCount = readNBytes(parameters.getPayload(), chunkBuffer, bufferSize);
|
||||
var bytesCount = readNBytes(args.getPayload(), chunkBuffer, bufferSize);
|
||||
|
||||
if (bytesCount == 0) {
|
||||
break;
|
||||
|
@ -204,110 +272,40 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
return new PutObjectResult(objectId, sentBytes);
|
||||
}
|
||||
|
||||
private ObjectId putClientCutObject(PutObjectParameters parameters) {
|
||||
var header = parameters.getHeader();
|
||||
var tokenRaw = getOrCreateSession(parameters.getSessionToken());
|
||||
var token = new SessionToken(SessionMapper.serialize(tokenRaw));
|
||||
parameters.setSessionToken(token);
|
||||
|
||||
var fullLength = header.getPayloadLength() == 0
|
||||
? getStreamSize(parameters.getPayload())
|
||||
: header.getPayloadLength();
|
||||
|
||||
parameters.setFullLength(fullLength);
|
||||
|
||||
if (parameters.getMaxObjectSizeCache() == 0) {
|
||||
var networkSettings = getContext().getFrostFSClient().getNetworkSettings();
|
||||
parameters.setMaxObjectSizeCache(networkSettings.getMaxObjectSize().intValue());
|
||||
}
|
||||
|
||||
var restBytes = fullLength - parameters.getCurrentStreamPosition();
|
||||
var objectSize = restBytes > 0
|
||||
? Math.min(parameters.getMaxObjectSizeCache(), restBytes)
|
||||
: parameters.getMaxObjectSizeCache();
|
||||
|
||||
//define collection capacity
|
||||
var restPart = (restBytes % objectSize) > 0 ? 1 : 0;
|
||||
var objectsCount = fullLength > 0 ? (int) (restBytes / objectSize) + restPart : 0;
|
||||
|
||||
List<ObjectId> sentObjectIds = new ArrayList<>(objectsCount);
|
||||
|
||||
// keep attributes for the large object
|
||||
var attributes = parameters.getHeader().getAttributes();
|
||||
|
||||
Split split = new Split();
|
||||
parameters.getHeader().setSplit(split);
|
||||
parameters.getHeader().setAttributes(new ArrayList<>());
|
||||
|
||||
// send all parts except the last one as separate Objects
|
||||
while (restBytes > (long) parameters.getMaxObjectSizeCache()) {
|
||||
var previous = CollectionUtils.isNotEmpty(sentObjectIds)
|
||||
? sentObjectIds.get(sentObjectIds.size() - 1)
|
||||
: null;
|
||||
split.setPrevious(previous);
|
||||
|
||||
var result = putStreamObject(parameters);
|
||||
|
||||
sentObjectIds.add(result.getObjectId());
|
||||
|
||||
restBytes -= result.getObjectSize();
|
||||
}
|
||||
|
||||
// send the last part and create linkObject
|
||||
if (CollectionUtils.isNotEmpty(sentObjectIds)) {
|
||||
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();
|
||||
}
|
||||
|
||||
// We are here if the payload is placed to one Object. It means no cut action, just simple PUT.
|
||||
var singlePartResult = putStreamObject(parameters);
|
||||
|
||||
return singlePartResult.getObjectId();
|
||||
}
|
||||
|
||||
private ObjectWriter getUploadStream(PutObjectParameters parameters) {
|
||||
var header = parameters.getHeader();
|
||||
private ObjectStreamer getUploadStream(PrmObjectPutBase args, CallContext ctx) {
|
||||
var header = args.getObjectHeader();
|
||||
|
||||
header.setOwnerId(getContext().getOwnerId());
|
||||
header.setVersion(getContext().getVersion());
|
||||
|
||||
var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header);
|
||||
|
||||
if (nonNull(header.getSplit())) {
|
||||
grpcHeader = objectToolsImpl.updateSplitValues(grpcHeader, header.getSplit());
|
||||
}
|
||||
|
||||
var oid = Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build();
|
||||
|
||||
var initRequest = createInitPutRequest(oid, grpcHeader);
|
||||
var initRequest = createInitPutRequest(oid, grpcHeader, args, ctx);
|
||||
|
||||
return putObjectInit(initRequest);
|
||||
return putObjectInit(initRequest, ctx);
|
||||
}
|
||||
|
||||
private ObjectWriter putObjectInit(Service.PutRequest initRequest) {
|
||||
private ObjectStreamer putObjectInit(Service.PutRequest initRequest, CallContext ctx) {
|
||||
if (initRequest.getSerializedSize() == 0) {
|
||||
throw new ProcessFrostFSException(
|
||||
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, initRequest.getClass().getName())
|
||||
);
|
||||
}
|
||||
|
||||
ObjectWriter writer = new ObjectWriter(objectServiceClient);
|
||||
var service = deadLineAfter(objectServiceClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
ObjectStreamer writer = new ObjectStreamer(service);
|
||||
writer.write(initRequest);
|
||||
return writer;
|
||||
}
|
||||
|
||||
private Iterable<Types.ObjectID> searchObjects(Service.SearchRequest request) {
|
||||
var reader = getSearchReader(request);
|
||||
private Iterable<Types.ObjectID> searchObjects(Service.SearchRequest request, CallContext ctx) {
|
||||
var reader = getSearchReader(request, ctx);
|
||||
var ids = reader.read();
|
||||
List<Types.ObjectID> result = new ArrayList<>();
|
||||
|
||||
|
@ -319,14 +317,15 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
return result;//todo return yield
|
||||
}
|
||||
|
||||
private SearchReader getSearchReader(Service.SearchRequest initRequest) {
|
||||
private SearchReader getSearchReader(Service.SearchRequest initRequest, CallContext ctx) {
|
||||
if (initRequest.getSerializedSize() == 0) {
|
||||
throw new ProcessFrostFSException(
|
||||
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, initRequest.getClass().getName())
|
||||
);
|
||||
}
|
||||
|
||||
return new SearchReader(objectServiceBlockingClient.search(initRequest));
|
||||
var service = deadLineAfter(objectServiceBlockingClient, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
return new SearchReader(service.search(initRequest));
|
||||
}
|
||||
|
||||
private int readNBytes(InputStream inputStream, byte[] buffer, int size) {
|
||||
|
@ -345,36 +344,37 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
}
|
||||
}
|
||||
|
||||
private Service.HeadRequest createHeadRequest(Types.ContainerID cid, Types.ObjectID oid) {
|
||||
private Service.HeadRequest createHeadRequest(PrmObjectHeadGet args, CallContext ctx) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setObjectId(oid)
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(args.getContainerId()))
|
||||
.setObjectId(ObjectIdMapper.toGrpcMessage(args.getObjectId()))
|
||||
.build();
|
||||
var body = Service.HeadRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
.setRaw(args.isRaw())
|
||||
.build();
|
||||
var request = Service.HeadRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.HEAD,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.GetRequest createGetRequest(Types.ContainerID cid, Types.ObjectID oid) {
|
||||
private Service.GetRequest createGetRequest(PrmObjectGet args, CallContext ctx) {
|
||||
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setObjectId(oid)
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(args.getContainerId()))
|
||||
.setObjectId(ObjectIdMapper.toGrpcMessage(args.getObjectId()))
|
||||
.build();
|
||||
var body = Service.GetRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
|
@ -382,25 +382,24 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
var request = Service.GetRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.GET,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.DeleteRequest createDeleteRequest(Types.ContainerID cid, Types.ObjectID oid) {
|
||||
private Service.DeleteRequest createDeleteRequest(PrmObjectDelete args, CallContext ctx) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.setObjectId(oid)
|
||||
.setContainerId(ContainerIdMapper.toGrpcMessage(args.getContainerId()))
|
||||
.setObjectId(ObjectIdMapper.toGrpcMessage(args.getObjectId()))
|
||||
.build();
|
||||
var body = Service.DeleteRequest.Body.newBuilder()
|
||||
.setAddress(address)
|
||||
|
@ -408,22 +407,23 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
var request = Service.DeleteRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.DELETE,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.SearchRequest createSearchRequest(Types.ContainerID cid, ObjectFilter<?>... filters) {
|
||||
private Service.SearchRequest createSearchRequest(PrmObjectSearch args, CallContext ctx) {
|
||||
var cid = ContainerIdMapper.toGrpcMessage(args.getContainerId());
|
||||
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(cid)
|
||||
.build();
|
||||
|
@ -432,29 +432,31 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
.setContainerId(cid)
|
||||
.setVersion(1);// TODO: clarify this param
|
||||
|
||||
for (ObjectFilter<?> filter : filters) {
|
||||
for (ObjectFilter<?> filter : args.getFilters()) {
|
||||
body.addFilters(ObjectFilterMapper.toGrpcMessage(filter));
|
||||
}
|
||||
|
||||
var request = Service.SearchRequest.newBuilder()
|
||||
.setBody(body.build());
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.SEARCH,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.PutRequest createInitPutRequest(Types.ObjectID oid, frostfs.object.Types.Header header) {
|
||||
private Service.PutRequest createInitPutRequest(Types.ObjectID oid,
|
||||
frostfs.object.Types.Header header,
|
||||
PrmObjectPutBase args,
|
||||
CallContext ctx) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(header.getContainerId())
|
||||
.setObjectId(oid)
|
||||
|
@ -468,22 +470,23 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
var request = Service.PutRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.PUT,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
}
|
||||
|
||||
private Service.PutSingleRequest createPutSingleRequest(frostfs.object.Types.Object grpcObject) {
|
||||
private Service.PutSingleRequest createPutSingleRequest(frostfs.object.Types.Object grpcObject,
|
||||
PrmObjectSinglePut args,
|
||||
CallContext ctx) {
|
||||
var address = Types.Address.newBuilder()
|
||||
.setContainerId(grpcObject.getHeader().getContainerId())
|
||||
.setObjectId(grpcObject.getObjectId())
|
||||
|
@ -494,16 +497,15 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
|
|||
var request = Service.PutSingleRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
||||
var sessionToken = getOrCreateSession(null);
|
||||
|
||||
sessionToken = RequestConstructor.createObjectTokenContext(
|
||||
var sessionToken = getOrCreateSession(args, ctx);
|
||||
var protoToken = RequestConstructor.createObjectTokenContext(
|
||||
sessionToken,
|
||||
address,
|
||||
frostfs.session.Types.ObjectSessionContext.Verb.PUT,
|
||||
getContext().getKey()
|
||||
);
|
||||
|
||||
RequestConstructor.addMetaHeader(request, null, sessionToken);
|
||||
RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return request.build();
|
||||
|
|
|
@ -5,6 +5,8 @@ import frostfs.session.SessionServiceGrpc;
|
|||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.session.PrmSessionCreate;
|
||||
import info.frostfs.sdk.mappers.object.OwnerIdMapper;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
|
@ -13,6 +15,7 @@ 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.utils.DeadLineUtil.deadLineAfter;
|
||||
|
||||
public class SessionClientImpl extends ContextAccessor implements SessionClient {
|
||||
private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub;
|
||||
|
@ -23,16 +26,16 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
|
|||
}
|
||||
|
||||
@Override
|
||||
public SessionToken createSession(long expiration) {
|
||||
var sessionToken = createSessionInternal(expiration);
|
||||
public SessionToken createSession(PrmSessionCreate args, CallContext ctx) {
|
||||
var sessionToken = createSessionInternal(args, ctx);
|
||||
var token = SessionMapper.serialize(sessionToken);
|
||||
return new SessionToken(token);
|
||||
}
|
||||
|
||||
public Types.SessionToken createSessionInternal(long expiration) {
|
||||
public Types.SessionToken createSessionInternal(PrmSessionCreate args, CallContext ctx) {
|
||||
var body = Service.CreateRequest.Body.newBuilder()
|
||||
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
|
||||
.setExpiration(expiration)
|
||||
.setExpiration(args.getExpiration())
|
||||
.build();
|
||||
var request = Service.CreateRequest.newBuilder()
|
||||
.setBody(body);
|
||||
|
@ -40,11 +43,12 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
|
|||
RequestConstructor.addMetaHeader(request);
|
||||
sign(request, getContext().getKey());
|
||||
|
||||
return createSession(request.build());
|
||||
return createSession(request.build(), ctx);
|
||||
}
|
||||
|
||||
private Types.SessionToken createSession(Service.CreateRequest request) {
|
||||
var response = serviceBlockingStub.create(request);
|
||||
private Types.SessionToken createSession(Service.CreateRequest request, CallContext ctx) {
|
||||
var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
|
||||
var response = service.create(request);
|
||||
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package info.frostfs.sdk.services.impl;
|
||||
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.exceptions.FrostFSException;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.session.PrmSessionCreate;
|
||||
import info.frostfs.sdk.services.ContextAccessor;
|
||||
import info.frostfs.sdk.services.SessionTools;
|
||||
|
||||
import static info.frostfs.sdk.constants.ErrorConst.SESSION_CREATE_FAILED;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class SessionToolsImpl extends ContextAccessor implements SessionTools {
|
||||
|
@ -16,11 +18,18 @@ public class SessionToolsImpl extends ContextAccessor implements SessionTools {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Types.SessionToken getOrCreateSession(SessionToken sessionToken, ClientEnvironment env) {
|
||||
if (isNull(sessionToken)) {
|
||||
return env.getFrostFSClient().createSessionInternal(-1);
|
||||
public SessionToken getOrCreateSession(ClientEnvironment env, CallContext ctx) {
|
||||
var token = env.getSessionCache().tryGetValue(env.getSessionKey());
|
||||
|
||||
if (isNull(token)) {
|
||||
token = env.getFrostFSClient().createSession(new PrmSessionCreate(-1), ctx);
|
||||
if (isNull(token)) {
|
||||
throw new FrostFSException(SESSION_CREATE_FAILED);
|
||||
}
|
||||
|
||||
return SessionMapper.deserializeSessionToken(sessionToken.getToken());
|
||||
env.getSessionCache().setValue(env.getSessionKey(), token);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package info.frostfs.sdk.services.impl.interceptor;
|
|||
|
||||
|
||||
import io.prometheus.client.CollectorRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Configuration {
|
||||
private static final double[] DEFAULT_LATENCY_BUCKETS =
|
||||
new double[]{.001, .005, .01, .05, 0.075, .1, .25, .5, 1, 2, 5, 10};
|
||||
|
@ -14,6 +16,7 @@ public class Configuration {
|
|||
private final double[] latencyBuckets;
|
||||
private final List<String> labelHeaders;
|
||||
private final boolean isAddCodeLabelToHistograms;
|
||||
|
||||
private Configuration(
|
||||
boolean isIncludeLatencyHistograms,
|
||||
CollectorRegistry collectorRegistry,
|
||||
|
@ -28,7 +31,9 @@ public class Configuration {
|
|||
}
|
||||
|
||||
|
||||
/** Returns a {@link Configuration} for recording all cheap metrics about the rpcs. */
|
||||
/**
|
||||
* Returns a {@link Configuration} for recording all cheap metrics about the rpcs.
|
||||
*/
|
||||
public static Configuration cheapMetricsOnly() {
|
||||
return new Configuration(
|
||||
false /* isIncludeLatencyHistograms */,
|
||||
|
@ -119,27 +124,37 @@ public class Configuration {
|
|||
true /* isAddCodeLabelToHistograms */);
|
||||
}
|
||||
|
||||
/** Returns whether or not latency histograms for calls should be included. */
|
||||
/**
|
||||
* Returns whether or not latency histograms for calls should be included.
|
||||
*/
|
||||
public boolean isIncludeLatencyHistograms() {
|
||||
return isIncludeLatencyHistograms;
|
||||
}
|
||||
|
||||
/** Returns the {@link CollectorRegistry} used to record stats. */
|
||||
/**
|
||||
* Returns the {@link CollectorRegistry} used to record stats.
|
||||
*/
|
||||
public CollectorRegistry getCollectorRegistry() {
|
||||
return collectorRegistry;
|
||||
}
|
||||
|
||||
/** Returns the histogram buckets to use for latency metrics. */
|
||||
/**
|
||||
* Returns the histogram buckets to use for latency metrics.
|
||||
*/
|
||||
public double[] getLatencyBuckets() {
|
||||
return latencyBuckets;
|
||||
}
|
||||
|
||||
/** Returns the configured list of headers to be used as labels. */
|
||||
/**
|
||||
* Returns the configured list of headers to be used as labels.
|
||||
*/
|
||||
public List<String> getLabelHeaders() {
|
||||
return labelHeaders;
|
||||
}
|
||||
|
||||
/** Returns whether or not status code label should be added to latency histogram. */
|
||||
/**
|
||||
* Returns whether or not status code label should be added to latency histogram.
|
||||
*/
|
||||
public boolean isAddCodeLabelToHistograms() {
|
||||
return isAddCodeLabelToHistograms;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package info.frostfs.sdk.services.impl.rwhelper;
|
||||
|
||||
import frostfs.object.ObjectServiceGrpc;
|
||||
import frostfs.object.Service;
|
||||
import info.frostfs.sdk.exceptions.ProcessFrostFSException;
|
||||
import info.frostfs.sdk.utils.WaitUtil;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import lombok.Getter;
|
||||
|
||||
import static info.frostfs.sdk.constants.ErrorConst.PROTO_MESSAGE_IS_EMPTY_TEMPLATE;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ObjectStreamer {
|
||||
private static final long POLL_INTERVAL = 10;
|
||||
private final StreamObserver<Service.PutRequest> requestObserver;
|
||||
private final PutResponseCallback responseObserver;
|
||||
|
||||
public ObjectStreamer(ObjectServiceGrpc.ObjectServiceStub objectServiceStub) {
|
||||
PutResponseCallback responseObserver = new PutResponseCallback();
|
||||
|
||||
this.responseObserver = responseObserver;
|
||||
this.requestObserver = objectServiceStub.put(responseObserver);
|
||||
}
|
||||
|
||||
public void write(Service.PutRequest request) {
|
||||
if (isNull(request)) {
|
||||
throw new ProcessFrostFSException(
|
||||
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, Service.PutRequest.class.getName())
|
||||
);
|
||||
}
|
||||
requestObserver.onNext(request);
|
||||
}
|
||||
|
||||
public Service.PutResponse complete() {
|
||||
requestObserver.onCompleted();
|
||||
|
||||
while (isNull(responseObserver.getResponse())) {
|
||||
WaitUtil.sleep(POLL_INTERVAL);
|
||||
}
|
||||
|
||||
return responseObserver.getResponse();
|
||||
}
|
||||
|
||||
@Getter
|
||||
private static class PutResponseCallback implements StreamObserver<Service.PutResponse> {
|
||||
private Service.PutResponse response;
|
||||
|
||||
@Override
|
||||
public void onNext(Service.PutResponse putResponse) {
|
||||
this.response = putResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
throw new ProcessFrostFSException(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +1,41 @@
|
|||
package info.frostfs.sdk.services.impl.rwhelper;
|
||||
|
||||
import frostfs.object.ObjectServiceGrpc;
|
||||
import com.google.protobuf.ByteString;
|
||||
import frostfs.object.Service;
|
||||
import info.frostfs.sdk.exceptions.ProcessFrostFSException;
|
||||
import info.frostfs.sdk.utils.WaitUtil;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.object.PrmObjectPutBase;
|
||||
import info.frostfs.sdk.tools.Verifier;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import static info.frostfs.sdk.constants.ErrorConst.PROTO_MESSAGE_IS_EMPTY_TEMPLATE;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ObjectWriter {
|
||||
private static final long POLL_INTERVAL = 10;
|
||||
private final StreamObserver<Service.PutRequest> requestObserver;
|
||||
private final PutResponseCallback responseObserver;
|
||||
|
||||
public ObjectWriter(ObjectServiceGrpc.ObjectServiceStub objectServiceStub) {
|
||||
PutResponseCallback responseObserver = new PutResponseCallback();
|
||||
|
||||
this.responseObserver = responseObserver;
|
||||
this.requestObserver = objectServiceStub.put(responseObserver);
|
||||
}
|
||||
|
||||
public void write(Service.PutRequest request) {
|
||||
if (isNull(request)) {
|
||||
throw new ProcessFrostFSException(
|
||||
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, Service.PutRequest.class.getName())
|
||||
);
|
||||
}
|
||||
|
||||
requestObserver.onNext(request);
|
||||
}
|
||||
|
||||
public Service.PutResponse complete() {
|
||||
requestObserver.onCompleted();
|
||||
|
||||
while (isNull(responseObserver.getResponse())) {
|
||||
WaitUtil.sleep(POLL_INTERVAL);
|
||||
}
|
||||
|
||||
return responseObserver.getResponse();
|
||||
}
|
||||
import static info.frostfs.sdk.tools.RequestSigner.sign;
|
||||
|
||||
//todo specify a deadline for each stream request, not for the entire stream
|
||||
@Getter
|
||||
private static class PutResponseCallback implements StreamObserver<Service.PutResponse> {
|
||||
private Service.PutResponse response;
|
||||
@AllArgsConstructor
|
||||
public class ObjectWriter {
|
||||
private final ClientEnvironment environment;
|
||||
private final PrmObjectPutBase args;
|
||||
private final ObjectStreamer streamer;
|
||||
|
||||
@Override
|
||||
public void onNext(Service.PutResponse putResponse) {
|
||||
this.response = putResponse;
|
||||
public void write(byte[] buffer) {
|
||||
var body = Service.PutRequest.Body.newBuilder()
|
||||
.setChunk(ByteString.copyFrom(buffer))
|
||||
.build();
|
||||
var chunkRequest = Service.PutRequest.newBuilder()
|
||||
.setBody(body)
|
||||
.clearVerifyHeader();
|
||||
|
||||
sign(chunkRequest, environment.getKey());
|
||||
|
||||
streamer.write(chunkRequest.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
throw new ProcessFrostFSException(throwable);
|
||||
}
|
||||
public ObjectId complete() {
|
||||
var response = streamer.complete();
|
||||
Verifier.checkResponse(response);
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
}
|
||||
return new ObjectId(response.getBody().getObjectId().getValue().toByteArray());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@ import com.google.protobuf.ByteString;
|
|||
import com.google.protobuf.Message;
|
||||
import frostfs.session.Types;
|
||||
import info.frostfs.sdk.dto.response.MetaHeader;
|
||||
import info.frostfs.sdk.dto.session.SessionToken;
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.ECDsa;
|
||||
import info.frostfs.sdk.mappers.response.MetaHeaderMapper;
|
||||
import info.frostfs.sdk.mappers.session.SessionMapper;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -65,13 +67,11 @@ public class RequestConstructor {
|
|||
setField(request, META_HEADER_FIELD_NAME, metaHeader.build());
|
||||
}
|
||||
|
||||
public static Types.SessionToken createObjectTokenContext(Types.SessionToken sessionToken,
|
||||
public static Types.SessionToken createObjectTokenContext(SessionToken sessionToken,
|
||||
frostfs.refs.Types.Address address,
|
||||
Types.ObjectSessionContext.Verb verb,
|
||||
ECDsa key) {
|
||||
if (isNull(sessionToken) || sessionToken.getBody().getObject().getTarget().getSerializedSize() > 0) {
|
||||
return sessionToken;
|
||||
}
|
||||
var protoToken = SessionMapper.deserializeSessionToken(sessionToken.getToken());
|
||||
|
||||
var target = Types.ObjectSessionContext.Target.newBuilder()
|
||||
.setContainer(address.getContainerId());
|
||||
|
@ -84,25 +84,23 @@ public class RequestConstructor {
|
|||
.setTarget(target.build())
|
||||
.setVerb(verb)
|
||||
.build();
|
||||
var body = sessionToken.getBody().toBuilder()
|
||||
var body = protoToken.getBody().toBuilder()
|
||||
.setObject(ctx)
|
||||
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()))
|
||||
.build();
|
||||
|
||||
return sessionToken.toBuilder()
|
||||
return protoToken.toBuilder()
|
||||
.setSignature(signMessagePart(key, body))
|
||||
.setBody(body)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Types.SessionToken createContainerTokenContext(Types.SessionToken sessionToken,
|
||||
public static Types.SessionToken createContainerTokenContext(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 protoToken = SessionMapper.deserializeSessionToken(sessionToken.getToken());
|
||||
|
||||
var containerSession = Types.ContainerSessionContext.newBuilder().setVerb(verb);
|
||||
|
||||
|
@ -112,7 +110,7 @@ public class RequestConstructor {
|
|||
containerSession.setContainerId(containerId);
|
||||
}
|
||||
|
||||
var bodyBuilder = sessionToken.getBody().toBuilder()
|
||||
var bodyBuilder = protoToken.getBody().toBuilder()
|
||||
.setContainer(containerSession)
|
||||
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()));
|
||||
|
||||
|
@ -122,7 +120,7 @@ public class RequestConstructor {
|
|||
|
||||
var body = bodyBuilder.build();
|
||||
|
||||
return sessionToken.toBuilder()
|
||||
return protoToken.toBuilder()
|
||||
.setSignature(signMessagePart(key, body))
|
||||
.setBody(body)
|
||||
.build();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package info.frostfs.sdk.utils;
|
||||
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import io.grpc.stub.AbstractStub;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static info.frostfs.sdk.constants.ErrorConst.PARAM_IS_MISSING_TEMPLATE;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class DeadLineUtil {
|
||||
private DeadLineUtil() {
|
||||
}
|
||||
|
||||
public static <T extends AbstractStub<T>> T deadLineAfter(T stub, long deadLine, TimeUnit timeUnit) {
|
||||
if (isNull(stub)) {
|
||||
throw new ValidationFrostFSException(
|
||||
String.format(PARAM_IS_MISSING_TEMPLATE, AbstractStub.class.getName())
|
||||
);
|
||||
}
|
||||
|
||||
timeUnit = isNull(timeUnit) ? TimeUnit.MILLISECONDS : timeUnit;
|
||||
return deadLine > 0 ? stub.withDeadlineAfter(deadLine, timeUnit) : stub;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import frostfs.accounting.Service;
|
|||
import info.frostfs.sdk.Base58;
|
||||
import info.frostfs.sdk.dto.object.OwnerId;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.services.impl.AccountingClientImpl;
|
||||
import info.frostfs.sdk.testgenerator.AccountingGenerator;
|
||||
import info.frostfs.sdk.tools.RequestConstructor;
|
||||
|
@ -81,11 +82,11 @@ class AccountingClientTest {
|
|||
when(AccountingServiceClient.balance(captor.capture())).thenReturn(response);
|
||||
|
||||
//When
|
||||
var result = accountingClient.getBalance();
|
||||
var result = accountingClient.getBalance(new CallContext(0, null));
|
||||
|
||||
//Then
|
||||
requestConstructorMock.verify(
|
||||
() -> RequestConstructor.addMetaHeader(any(Service.BalanceRequest.Builder.class), eq(null)),
|
||||
() -> RequestConstructor.addMetaHeader(any(Service.BalanceRequest.Builder.class)),
|
||||
times(1)
|
||||
);
|
||||
requestSignerMock.verify(
|
||||
|
|
|
@ -8,6 +8,10 @@ import info.frostfs.sdk.dto.chain.ChainTarget;
|
|||
import info.frostfs.sdk.enums.TargetType;
|
||||
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
|
||||
import info.frostfs.sdk.jdo.ClientEnvironment;
|
||||
import info.frostfs.sdk.jdo.parameters.CallContext;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainAdd;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainList;
|
||||
import info.frostfs.sdk.jdo.parameters.ape.PrmApeChainRemove;
|
||||
import info.frostfs.sdk.services.impl.ApeManagerClientImpl;
|
||||
import info.frostfs.sdk.testgenerator.ApeManagerGenerator;
|
||||
import info.frostfs.sdk.tools.RequestConstructor;
|
||||
|
@ -78,6 +82,7 @@ class ApeManagerClientTest {
|
|||
//Given
|
||||
Chain chain = generateChain();
|
||||
ChainTarget chainTarget = generateChainTarget();
|
||||
PrmApeChainAdd params = new PrmApeChainAdd(chain, chainTarget);
|
||||
|
||||
var response = ApeManagerGenerator.generateAddChainResponse();
|
||||
|
||||
|
@ -86,7 +91,7 @@ class ApeManagerClientTest {
|
|||
when(apeManagerServiceClient.addChain(captor.capture())).thenReturn(response);
|
||||
|
||||
//When
|
||||
var result = apeManagerClient.addChain(chain, chainTarget);
|
||||
var result = apeManagerClient.addChain(params, new CallContext(0, null));
|
||||
|
||||
//Then
|
||||
requestConstructorMock.verify(
|
||||
|
@ -112,11 +117,15 @@ class ApeManagerClientTest {
|
|||
//Given
|
||||
Chain chain = generateChain();
|
||||
ChainTarget chainTarget = generateChainTarget();
|
||||
PrmApeChainAdd params1 = new PrmApeChainAdd(null, chainTarget);
|
||||
PrmApeChainAdd params2 = new PrmApeChainAdd(chain, null);
|
||||
PrmApeChainAdd params3 = new PrmApeChainAdd(null, null);
|
||||
|
||||
|
||||
//When + Then
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(null, chainTarget));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(chain, null));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(null, null));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(params1, new CallContext()));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(params2, new CallContext()));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(params3, new CallContext()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -124,6 +133,7 @@ class ApeManagerClientTest {
|
|||
//Given
|
||||
Chain chain = generateChain();
|
||||
ChainTarget chainTarget = generateChainTarget();
|
||||
PrmApeChainRemove params = new PrmApeChainRemove(chain, chainTarget);
|
||||
|
||||
var response = ApeManagerGenerator.generateRemoveChainResponse();
|
||||
|
||||
|
@ -132,7 +142,7 @@ class ApeManagerClientTest {
|
|||
when(apeManagerServiceClient.removeChain(captor.capture())).thenReturn(response);
|
||||
|
||||
//When
|
||||
apeManagerClient.removeChain(chain, chainTarget);
|
||||
apeManagerClient.removeChain(params, new CallContext(0, null));
|
||||
|
||||
//Then
|
||||
requestConstructorMock.verify(
|
||||
|
@ -156,17 +166,21 @@ class ApeManagerClientTest {
|
|||
//Given
|
||||
Chain chain = generateChain();
|
||||
ChainTarget chainTarget = generateChainTarget();
|
||||
PrmApeChainRemove params1 = new PrmApeChainRemove(null, chainTarget);
|
||||
PrmApeChainRemove params2 = new PrmApeChainRemove(chain, null);
|
||||
PrmApeChainRemove params3 = new PrmApeChainRemove(null, null);
|
||||
|
||||
//When + Then
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(null, chainTarget));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(chain, null));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(null, null));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(params1, new CallContext()));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(params2, new CallContext()));
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(params3, new CallContext()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void listChain_success() {
|
||||
//Given
|
||||
ChainTarget chainTarget = generateChainTarget();
|
||||
PrmApeChainList params = new PrmApeChainList(chainTarget);
|
||||
|
||||
var response = ApeManagerGenerator.generateListChainsResponse();
|
||||
|
||||
|
@ -175,7 +189,7 @@ class ApeManagerClientTest {
|
|||
when(apeManagerServiceClient.listChains(captor.capture())).thenReturn(response);
|
||||
|
||||
//When
|
||||
var result = apeManagerClient.listChains(chainTarget);
|
||||
var result = apeManagerClient.listChains(params, new CallContext(0, null));
|
||||
|
||||
//Then
|
||||
requestConstructorMock.verify(
|
||||
|
@ -202,7 +216,8 @@ class ApeManagerClientTest {
|
|||
@Test
|
||||
void listChain_wrongParams() {
|
||||
//When + Then
|
||||
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.listChains(null));
|
||||
assertThrows(ValidationFrostFSException.class,
|
||||
() -> apeManagerClient.listChains(new PrmApeChainList(null), new CallContext()));
|
||||
}
|
||||
|
||||
private Chain generateChain() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>frostfs-sdk-java</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>cryptography</artifactId>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>exceptions</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>frostfs-sdk-java</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>exceptions</artifactId>
|
||||
|
|
|
@ -46,6 +46,8 @@ public class ErrorConst {
|
|||
public static final String POOL_CLIENTS_UNHEALTHY = "cannot find alive client";
|
||||
public static final String POOL_NOT_DIALED = "pool not dialed";
|
||||
|
||||
public static final String SESSION_CREATE_FAILED = "cannot create session";
|
||||
|
||||
public static final String FIELDS_DELIMITER_COMMA = ", ";
|
||||
public static final String FIELDS_DELIMITER_OR = " or ";
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>frostfs-sdk-java</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>models</artifactId>
|
||||
|
@ -21,17 +21,17 @@
|
|||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>cryptography</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>protos</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>exceptions</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ public class AppConst {
|
|||
public static final int OBJECT_CHUNK_SIZE = 3 * MIB;
|
||||
public static final int SHA256_HASH_LENGTH = 32;
|
||||
public static final int UUID_BYTE_ARRAY_LENGTH = 16;
|
||||
public static final int DEFAULT_GRPC_TIMEOUT = 5;
|
||||
|
||||
private AppConst() {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package info.frostfs.sdk.dto.object;
|
||||
|
||||
import frostfs.object.Types;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class SplitInfo {
|
||||
private final Types.SplitInfo splitInfo;
|
||||
|
||||
private final SplitId splitId;
|
||||
|
||||
private final ObjectId link;
|
||||
|
||||
private final ObjectId lastPart;
|
||||
}
|
|
@ -13,7 +13,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static info.frostfs.sdk.UuidExtension.asBytes;
|
||||
import static info.frostfs.sdk.UuidExtension.asUuid;
|
||||
import static info.frostfs.sdk.constants.AttributeConst.DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE;
|
||||
import static info.frostfs.sdk.constants.ErrorConst.UNKNOWN_ENUM_VALUE_TEMPLATE;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
|
@ -31,7 +30,6 @@ public class ContainerMapper {
|
|||
.setPlacementPolicy(PlacementPolicyMapper.toGrpcMessage(container.getPlacementPolicy()))
|
||||
.setNonce(ByteString.copyFrom(asBytes(container.getNonce())));
|
||||
|
||||
container.getAttributes().putIfAbsent(DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE, Boolean.TRUE.toString());
|
||||
var attributes = container.getAttributes().entrySet().stream()
|
||||
.map(entry ->
|
||||
Types.Container.Attribute.newBuilder()
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package info.frostfs.sdk.mappers.object;
|
||||
|
||||
import frostfs.object.Types;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.object.SplitId;
|
||||
import info.frostfs.sdk.dto.object.SplitInfo;
|
||||
|
||||
import static info.frostfs.sdk.UuidExtension.asUuid;
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class SplitInfoMapper {
|
||||
private SplitInfoMapper() {
|
||||
}
|
||||
|
||||
public static SplitInfo toModel(Types.SplitInfo splitInfo) {
|
||||
if (isNull(splitInfo) || splitInfo.getSerializedSize() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var splitId = new SplitId(asUuid(splitInfo.getSplitId().toByteArray()));
|
||||
var link = splitInfo.getLink().getSerializedSize() == 0
|
||||
? null
|
||||
: new ObjectId(splitInfo.getLink().getValue().toByteArray());
|
||||
var lastPart = splitInfo.getLastPart().getSerializedSize() == 0
|
||||
? null
|
||||
: new ObjectId(splitInfo.getLastPart().getValue().toByteArray());
|
||||
|
||||
return new SplitInfo(splitInfo, splitId, link, lastPart);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package info.frostfs.sdk.mappers.object;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import frostfs.object.Types;
|
||||
import info.frostfs.sdk.dto.object.ObjectId;
|
||||
import info.frostfs.sdk.dto.object.SplitId;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class SplitInfoMapperTest {
|
||||
@Test
|
||||
void toModel_successLastPart() {
|
||||
//Given
|
||||
var splitId = new SplitId();
|
||||
var objectId = new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww");
|
||||
var splitInfo = Types.SplitInfo.newBuilder()
|
||||
.setSplitId(ByteString.copyFrom(splitId.toBinary()))
|
||||
.setLastPart(ObjectIdMapper.toGrpcMessage(objectId))
|
||||
.build();
|
||||
|
||||
//When
|
||||
var result = SplitInfoMapper.toModel(splitInfo);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
assertNull(result.getLink());
|
||||
assertThat(result.getSplitInfo()).isEqualTo(splitInfo);
|
||||
assertThat(result.getSplitId().toBinary()).containsExactly(splitId.toBinary());
|
||||
assertEquals(objectId.getValue(), result.getLastPart().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toModel_successLink() {
|
||||
//Given
|
||||
var splitId = new SplitId();
|
||||
var objectId = new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww");
|
||||
var splitInfo = Types.SplitInfo.newBuilder()
|
||||
.setSplitId(ByteString.copyFrom(splitId.toBinary()))
|
||||
.setLink(ObjectIdMapper.toGrpcMessage(objectId))
|
||||
.build();
|
||||
|
||||
//When
|
||||
var result = SplitInfoMapper.toModel(splitInfo);
|
||||
|
||||
//Then
|
||||
assertNotNull(result);
|
||||
assertNull(result.getLastPart());
|
||||
assertThat(result.getSplitInfo()).isEqualTo(splitInfo);
|
||||
assertThat(result.getSplitId().toBinary()).containsExactly(splitId.toBinary());
|
||||
assertEquals(objectId.getValue(), result.getLink().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toModel_null() {
|
||||
//When + Then
|
||||
assertNull(SplitInfoMapper.toModel(null));
|
||||
assertNull(SplitInfoMapper.toModel(Types.SplitInfo.getDefaultInstance()));
|
||||
}
|
||||
}
|
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>frostfs-sdk-java</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>client</module>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>info.frostfs.sdk</groupId>
|
||||
<artifactId>frostfs-sdk-java</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<version>0.3.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>protos</artifactId>
|
||||
|
|
Loading…
Add table
Reference in a new issue
There are several disadvantages to using Lombok’s @EqualsAndHashCode annotation. First, it can generate unwanted hash code collisions when two objects have different field values but the same hash code.
Second, it may not be compatible with other libraries and frameworks that rely on traditional implementations of equals() and hashCode().
Lastly, it can reduce readability by generating methods that aren’t explicitly defined in the class, making it more difficult to understand the logic of the code.
Unfortunately, a collision cannot be avoided in principle, since the hash code is int and due to the birthday problem we only need 77,163 objects before we have a 50/50 chance of hashCode collision(lombok and Objects hashcode realization very similar, just different multiplier). But I agree about the second one, I’ll correct it.