[#34] Provide input parameters for all grpc methods #35

Merged
orikik merged 1 commit from orikik/frostfs-sdk-java:feature/input_params into master 2025-01-24 10:26:56 +00:00
61 changed files with 1411 additions and 625 deletions

112
README.md
View file

@ -21,31 +21,40 @@ neo-go wallet export -w <path_to_your_wallet> -d <address_from_p1>
### Container operations ### Container operations
```java ```java
import info.frostfs.sdk.FrostFSClient;
import info.frostfs.sdk.dto.container.Container; import info.frostfs.sdk.dto.container.Container;
import info.frostfs.sdk.dto.netmap.PlacementPolicy; import info.frostfs.sdk.dto.netmap.PlacementPolicy;
import info.frostfs.sdk.dto.netmap.Replica; import info.frostfs.sdk.dto.netmap.Replica;
import info.frostfs.sdk.enums.BasicAcl; import info.frostfs.sdk.enums.BasicAcl;
import info.frostfs.sdk.jdo.ClientSettings; 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 class ContainerExample {
public void example() { public void example() {
var callContext = new CallContext();
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>); ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
FrostFSClient frostFSClient = new FrostFSClient(clientSettings); FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
// Create container // Create container
var placementPolicy = new PlacementPolicy(new Replica[]{new Replica(1)}, Boolean.TRUE); var placementPolicy = new PlacementPolicy(new Replica[]{new Replica(1)}, true);
var containerId = frostFSClient.createContainer(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); var prmContainerCreate = new PrmContainerCreate(new Container(BasicAcl.PUBLIC_RW, placementPolicy));
var containerId = frostFSClient.createContainer(prmContainerCreate, callContext);
// Get container // Get container
var container = frostFSClient.getContainer(containerId); var prmContainerGet = new PrmContainerGet(containerId);
var container = frostFSClient.getContainer(prmContainerGet, callContext);
// List containers // List containers
var containerIds = frostFSClient.listContainers(); var containerIds = frostFSClient.listContainers(new PrmContainerGetAll(), callContext);
// Delete container // Delete container
frostFSClient.deleteContainer(containerId); var prmContainerDelete = new PrmContainerDelete(containerId);
frostFSClient.deleteContainer(prmContainerDelete, callContext);
} }
} }
``` ```
@ -53,45 +62,104 @@ public class ContainerExample {
### Object operations ### Object operations
```java ```java
import info.frostfs.sdk.dto.object.*;
import info.frostfs.sdk.enums.ObjectType; import info.frostfs.sdk.enums.ObjectType;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.jdo.ClientSettings;
import info.frostfs.sdk.dto.object.ObjectAttribute; import info.frostfs.sdk.jdo.parameters.CallContext;
import info.frostfs.sdk.dto.object.ObjectFilter; import info.frostfs.sdk.jdo.parameters.object.*;
import info.frostfs.sdk.dto.object.ObjectHeader; import org.apache.commons.lang3.ArrayUtils;
import info.frostfs.sdk.dto.object.ObjectId;
import info.frostfs.sdk.jdo.PutObjectParameters;
import info.frostfs.sdk.FrostFSClient;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import static java.util.Objects.isNull;
public class ObjectExample { public class ObjectExample {
public void example() { public void example() {
CallContext callContext = new CallContext();
ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>); ClientSettings clientSettings = new ClientSettings(<your_key>, <your_host>);
FrostFSClient frostFSClient = new FrostFSClient(clientSettings); FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
// Put object // Put object
ObjectId objectId; ObjectId objectId;
try (FileInputStream fis = new FileInputStream("cat.jpg")) { try (FileInputStream file = new FileInputStream("/path/to/file/cat.jpg")) {
var cat = new ObjectHeader( var attribute = new ObjectAttribute("Filename", "cat.jpg");
containerId, ObjectType.REGULAR, new ObjectAttribute[]{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); writer.write(file.readAllBytes());
objectId = frostFSClient.putObject(params); objectId = writer.complete();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// Get object // 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 // Get object header
var objectHeader = frostFSClient.getObjectHead(containerId, objectId); var prmObjectHeadGet = new PrmObjectHeadGet(containerId, objectId);
var objectHeader = frostFSClient.getObjectHead(prmObjectHeadGet, callContext);
// Search regular objects // 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);
} }
} }
``` ```

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>frostfs-sdk-java</artifactId> <artifactId>frostfs-sdk-java</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</parent> </parent>
<artifactId>client</artifactId> <artifactId>client</artifactId>
@ -21,17 +21,17 @@
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>cryptography</artifactId> <artifactId>cryptography</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>models</artifactId> <artifactId>models</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>exceptions</artifactId> <artifactId>exceptions</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>

View file

@ -2,13 +2,11 @@ package info.frostfs.sdk;
import frostfs.accounting.Types; import frostfs.accounting.Types;
import info.frostfs.sdk.dto.chain.Chain; 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.Container;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.dto.netmap.NetmapSnapshot; import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
import info.frostfs.sdk.dto.netmap.NodeInfo; import info.frostfs.sdk.dto.netmap.NodeInfo;
import info.frostfs.sdk.dto.netmap.Version; import info.frostfs.sdk.dto.netmap.Version;
import info.frostfs.sdk.dto.object.ObjectFilter;
import info.frostfs.sdk.dto.object.ObjectFrostFS; import info.frostfs.sdk.dto.object.ObjectFrostFS;
import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.dto.object.ObjectId; import info.frostfs.sdk.dto.object.ObjectId;
@ -17,13 +15,24 @@ import info.frostfs.sdk.exceptions.ProcessFrostFSException;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.jdo.ClientSettings; import info.frostfs.sdk.jdo.ClientSettings;
import info.frostfs.sdk.jdo.NetworkSettings; import info.frostfs.sdk.jdo.NetworkSettings;
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.SessionCache;
import info.frostfs.sdk.pool.WrapperPrm; import info.frostfs.sdk.pool.WrapperPrm;
import info.frostfs.sdk.services.CommonClient; import info.frostfs.sdk.services.CommonClient;
import info.frostfs.sdk.services.impl.*; import info.frostfs.sdk.services.impl.*;
import info.frostfs.sdk.services.impl.interceptor.Configuration; import info.frostfs.sdk.services.impl.interceptor.Configuration;
import info.frostfs.sdk.services.impl.interceptor.MonitoringClientInterceptor; import info.frostfs.sdk.services.impl.interceptor.MonitoringClientInterceptor;
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
import info.frostfs.sdk.utils.Validator; import info.frostfs.sdk.utils.Validator;
import io.grpc.Channel; import io.grpc.Channel;
import io.grpc.ClientInterceptors; import io.grpc.ClientInterceptors;
@ -55,8 +64,10 @@ public class FrostFSClient implements CommonClient {
: initGrpcChannel(clientSettings); : initGrpcChannel(clientSettings);
Channel interceptChannel = ClientInterceptors.intercept(channel, MONITORING_CLIENT_INTERCEPTOR); Channel interceptChannel = ClientInterceptors.intercept(channel, MONITORING_CLIENT_INTERCEPTOR);
ClientEnvironment clientEnvironment = ClientEnvironment clientEnvironment = new ClientEnvironment(
new ClientEnvironment(clientSettings.getKey(), interceptChannel, new Version(), this); clientSettings.getKey(), interceptChannel, new Version(), this,
new SessionCache(0)
);
Validator.validate(clientEnvironment); Validator.validate(clientEnvironment);
@ -75,7 +86,7 @@ public class FrostFSClient implements CommonClient {
Channel interceptChannel = ClientInterceptors.intercept(channel, MONITORING_CLIENT_INTERCEPTOR); Channel interceptChannel = ClientInterceptors.intercept(channel, MONITORING_CLIENT_INTERCEPTOR);
ClientEnvironment clientEnvironment = ClientEnvironment clientEnvironment =
new ClientEnvironment(prm.getKey(), interceptChannel, new Version(), this); new ClientEnvironment(prm.getKey(), interceptChannel, new Version(), this, cache);
Validator.validate(clientEnvironment); Validator.validate(clientEnvironment);
@ -90,7 +101,7 @@ public class FrostFSClient implements CommonClient {
} }
private void checkFrostFSVersionSupport(Version version) { private void checkFrostFSVersionSupport(Version version) {
var localNodeInfo = netmapClientImpl.getLocalNodeInfo(); var localNodeInfo = netmapClientImpl.getLocalNodeInfo(new CallContext());
if (!localNodeInfo.getVersion().isSupported(version)) { if (!localNodeInfo.getVersion().isSupported(version)) {
throw new ProcessFrostFSException( throw new ProcessFrostFSException(
String.format(VERSION_UNSUPPORTED_TEMPLATE, localNodeInfo.getVersion()) String.format(VERSION_UNSUPPORTED_TEMPLATE, localNodeInfo.getVersion())
@ -99,92 +110,97 @@ public class FrostFSClient implements CommonClient {
} }
@Override @Override
public Container getContainer(ContainerId cid) { public Container getContainer(PrmContainerGet args, CallContext ctx) {
return containerClientImpl.getContainer(cid); return containerClientImpl.getContainer(args, ctx);
} }
@Override @Override
public List<ContainerId> listContainers() { public List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx) {
return containerClientImpl.listContainers(); return containerClientImpl.listContainers(args, ctx);
} }
@Override @Override
public ContainerId createContainer(Container container) { public ContainerId createContainer(PrmContainerCreate args, CallContext ctx) {
return containerClientImpl.createContainer(container); return containerClientImpl.createContainer(args, ctx);
} }
@Override @Override
public void deleteContainer(ContainerId cid) { public void deleteContainer(PrmContainerDelete args, CallContext ctx) {
containerClientImpl.deleteContainer(cid); containerClientImpl.deleteContainer(args, ctx);
} }
@Override @Override
public ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId) { public ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx) {
return objectClientImpl.getObjectHead(containerId, objectId); return objectClientImpl.getObjectHead(args, ctx);
} }
@Override @Override
public ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId) { public ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx) {
return objectClientImpl.getObject(containerId, objectId); return objectClientImpl.getObject(args, ctx);
} }
@Override @Override
public ObjectId putObject(PutObjectParameters parameters) { public ObjectWriter putObject(PrmObjectPut args, CallContext ctx) {
return objectClientImpl.putObject(parameters); return objectClientImpl.putObject(args, ctx);
} }
@Override @Override
public ObjectId putSingleObject(ObjectFrostFS objectFrostFS) { public ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx) {
return objectClientImpl.putSingleObject(objectFrostFS); return objectClientImpl.putClientCutObject(args, ctx);
} }
@Override @Override
public void deleteObject(ContainerId containerId, ObjectId objectId) { public ObjectId putSingleObject(PrmObjectSinglePut args, CallContext ctx) {
objectClientImpl.deleteObject(containerId, objectId); return objectClientImpl.putSingleObject(args, ctx);
} }
@Override @Override
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) { public void deleteObject(PrmObjectDelete args, CallContext ctx) {
return objectClientImpl.searchObjects(cid, filters); objectClientImpl.deleteObject(args, ctx);
} }
@Override @Override
public byte[] addChain(Chain chain, ChainTarget chainTarget) { public Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx) {
return apeManagerClient.addChain(chain, chainTarget); return objectClientImpl.searchObjects(args, ctx);
} }
@Override @Override
public void removeChain(Chain chain, ChainTarget chainTarget) { public byte[] addChain(PrmApeChainAdd args, CallContext ctx) {
apeManagerClient.removeChain(chain, chainTarget); return apeManagerClient.addChain(args, ctx);
} }
@Override @Override
public List<Chain> listChains(ChainTarget chainTarget) { public void removeChain(PrmApeChainRemove args, CallContext ctx) {
return apeManagerClient.listChains(chainTarget); apeManagerClient.removeChain(args, ctx);
} }
@Override @Override
public NetmapSnapshot getNetmapSnapshot() { public List<Chain> listChains(PrmApeChainList args, CallContext ctx) {
return netmapClientImpl.getNetmapSnapshot(); return apeManagerClient.listChains(args, ctx);
} }
@Override @Override
public NodeInfo getLocalNodeInfo() { public NetmapSnapshot getNetmapSnapshot(CallContext ctx) {
return netmapClientImpl.getLocalNodeInfo(); return netmapClientImpl.getNetmapSnapshot(ctx);
} }
@Override @Override
public NetworkSettings getNetworkSettings() { public NodeInfo getLocalNodeInfo(CallContext ctx) {
return netmapClientImpl.getNetworkSettings(); return netmapClientImpl.getLocalNodeInfo(ctx);
} }
@Override @Override
public SessionToken createSession(long expiration) { public NetworkSettings getNetworkSettings(CallContext ctx) {
return sessionClientImpl.createSession(expiration); return netmapClientImpl.getNetworkSettings(ctx);
} }
public frostfs.session.Types.SessionToken createSessionInternal(long expiration) { @Override
return sessionClientImpl.createSessionInternal(expiration); 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 @Override
@ -193,12 +209,12 @@ public class FrostFSClient implements CommonClient {
} }
@Override @Override
public Types.Decimal getBalance() { public Types.Decimal getBalance(CallContext ctx) {
return accountingClient.getBalance(); return accountingClient.getBalance(ctx);
} }
public String dial() { public String dial(CallContext ctx) {
accountingClient.getBalance(); accountingClient.getBalance(ctx);
return null; return null;
} }

View file

@ -5,9 +5,14 @@ import info.frostfs.sdk.annotations.NotNull;
import info.frostfs.sdk.annotations.Validate; import info.frostfs.sdk.annotations.Validate;
import info.frostfs.sdk.dto.netmap.Version; import info.frostfs.sdk.dto.netmap.Version;
import info.frostfs.sdk.dto.object.OwnerId; import info.frostfs.sdk.dto.object.OwnerId;
import info.frostfs.sdk.pool.SessionCache;
import io.grpc.Channel; import io.grpc.Channel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; 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 @Getter
@Setter @Setter
@ -15,35 +20,48 @@ public class ClientEnvironment {
@NotNull @NotNull
private final OwnerId ownerId; private final OwnerId ownerId;
@NotNull @NotNull
private final Version version; private final Version version;
@NotNull @NotNull
@Validate @Validate
private final ECDsa key; private final ECDsa key;
@NotNull @NotNull
private final Channel channel; private final Channel channel;
@NotNull @NotNull
private final FrostFSClient frostFSClient; private final FrostFSClient frostFSClient;
private String sessionKey;
private String address;
private NetworkSettings networkSettings; 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.key = new ECDsa(wif);
this.ownerId = new OwnerId(key.getPublicKeyByte()); this.ownerId = new OwnerId(key.getPublicKeyByte());
this.version = version; this.version = version;
this.channel = channel; this.channel = channel;
this.frostFSClient = frostFSClient; 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.key = key;
this.ownerId = new OwnerId(key.getPublicKeyByte()); this.ownerId = new OwnerId(key.getPublicKeyByte());
this.version = version; this.version = version;
this.channel = channel; this.channel = channel;
this.frostFSClient = frostFSClient; this.frostFSClient = frostFSClient;
this.sessionCache = sessionCache;
}
public String getSessionKey() {
if (StringUtils.isBlank(sessionKey)) {
this.sessionKey = formCacheKey(address, getHexString(key.getPublicKeyByte()));
}
return sessionKey;
} }
} }

View file

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

View file

@ -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;
Outdated
Review

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.

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.

Unfortunately, a collision cannot be avoided in principle, since the hash code is int and due to the [birthday problem](https://en.wikipedia.org/wiki/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.
private final TimeUnit timeUnit;
public CallContext() {
this.timeout = DEFAULT_GRPC_TIMEOUT;
this.timeUnit = TimeUnit.SECONDS;
}
}

View file

@ -1,4 +1,4 @@
package info.frostfs.sdk.jdo; package info.frostfs.sdk.jdo.parameters;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -8,14 +8,14 @@ import java.time.LocalDateTime;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class WaitParameters { public class PrmWait {
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(120); private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(120);
private static final Duration DEFAULT_POLL_INTERVAL = Duration.ofSeconds(5); private static final Duration DEFAULT_POLL_INTERVAL = Duration.ofSeconds(5);
private final Duration timeout; private final Duration timeout;
private final Duration pollInterval; private final Duration pollInterval;
public WaitParameters() { public PrmWait() {
this.timeout = DEFAULT_TIMEOUT; this.timeout = DEFAULT_TIMEOUT;
this.pollInterval = DEFAULT_POLL_INTERVAL; this.pollInterval = DEFAULT_POLL_INTERVAL;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,7 @@
package info.frostfs.sdk.jdo.parameters.session;
import info.frostfs.sdk.dto.session.SessionToken;
public interface SessionContext {
SessionToken getSessionToken();
}

View file

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

View file

@ -4,6 +4,7 @@ import info.frostfs.sdk.FrostFSClient;
import info.frostfs.sdk.enums.MethodIndex; import info.frostfs.sdk.enums.MethodIndex;
import info.frostfs.sdk.exceptions.ResponseFrostFSException; import info.frostfs.sdk.exceptions.ResponseFrostFSException;
import info.frostfs.sdk.exceptions.ValidationFrostFSException; import info.frostfs.sdk.exceptions.ValidationFrostFSException;
import info.frostfs.sdk.jdo.parameters.CallContext;
import info.frostfs.sdk.utils.WaitUtil; import info.frostfs.sdk.utils.WaitUtil;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@ -45,12 +46,12 @@ public class ClientWrapper extends ClientStatusMonitor {
} }
} }
public void dial() { public void dial(CallContext ctx) {
FrostFSClient client = getClient(); FrostFSClient client = getClient();
if (client == null) { if (client == null) {
throw new ValidationFrostFSException(POOL_CLIENT_UNHEALTHY); throw new ValidationFrostFSException(POOL_CLIENT_UNHEALTHY);
} }
client.dial(); client.dial(ctx);
} }
public void handleError(Exception exp) { public void handleError(Exception exp) {
@ -77,9 +78,9 @@ public class ClientWrapper extends ClientStatusMonitor {
client.close(); client.close();
} }
public CompletableFuture<Boolean> restartIfUnhealthy() { public CompletableFuture<Boolean> restartIfUnhealthy(CallContext ctx) {
try { try {
client.getLocalNodeInfo(); client.getLocalNodeInfo(ctx);
return CompletableFuture.completedFuture(false); return CompletableFuture.completedFuture(false);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@ -88,15 +89,15 @@ public class ClientWrapper extends ClientStatusMonitor {
scheduleGracefulClose(); scheduleGracefulClose();
} }
return CompletableFuture.completedFuture(restartClient()); return CompletableFuture.completedFuture(restartClient(ctx));
} }
private boolean restartClient() { private boolean restartClient(CallContext ctx) {
FrostFSClient newClient = null; FrostFSClient newClient = null;
try { try {
newClient = new FrostFSClient(wrapperPrm, sessionCache); newClient = new FrostFSClient(wrapperPrm, sessionCache);
var error = newClient.dial(); var error = newClient.dial(ctx);
if (StringUtils.isNotBlank(error)) { if (StringUtils.isNotBlank(error)) {
setUnhealthyOnDial(); setUnhealthyOnDial();
newClient.close(); newClient.close();
@ -113,7 +114,7 @@ public class ClientWrapper extends ClientStatusMonitor {
} }
try { try {
client.getLocalNodeInfo(); client.getLocalNodeInfo(ctx);
} catch (Exception exp) { } catch (Exception exp) {
setUnhealthy(); setUnhealthy();
return true; return true;

View file

@ -2,12 +2,14 @@ package info.frostfs.sdk.pool;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.dto.chain.Chain; 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.Container;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.dto.netmap.NetmapSnapshot; import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
import info.frostfs.sdk.dto.netmap.NodeInfo; import info.frostfs.sdk.dto.netmap.NodeInfo;
import info.frostfs.sdk.dto.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.dto.session.SessionToken;
import info.frostfs.sdk.exceptions.FrostFSException; import info.frostfs.sdk.exceptions.FrostFSException;
import info.frostfs.sdk.exceptions.SessionExpiredFrostFSException; 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.exceptions.ValidationFrostFSException;
import info.frostfs.sdk.jdo.ECDsa; import info.frostfs.sdk.jdo.ECDsa;
import info.frostfs.sdk.jdo.NetworkSettings; 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.NodeParameters;
import info.frostfs.sdk.jdo.pool.PoolInitParameters; 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.CommonClient;
import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter;
import info.frostfs.sdk.utils.FrostFSMessages; import info.frostfs.sdk.utils.FrostFSMessages;
import info.frostfs.sdk.utils.WaitUtil; import info.frostfs.sdk.utils.WaitUtil;
import lombok.Getter; 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(); var client = cw.getClient();
NetworkSettings networkInfo = client.getNetworkSettings(); NetworkSettings networkInfo = client.getNetworkSettings(ctx);
long epoch = networkInfo.getEpochDuration(); long epoch = networkInfo.getEpochDuration();
long exp = (Long.MAX_VALUE - epoch < duration) ? Long.MAX_VALUE : (epoch + duration); 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; return address + key;
} }
public String dial() { public String dial(CallContext ctx) {
InnerPool[] inner = new InnerPool[rebalanceParams.getNodesParams().length]; InnerPool[] inner = new InnerPool[rebalanceParams.getNodesParams().length];
boolean atLeastOneHealthy = false; boolean atLeastOneHealthy = false;
int i = 0; int i = 0;
@ -198,10 +211,12 @@ public class Pool implements CommonClient {
boolean dialed = false; boolean dialed = false;
try { try {
client.dial(); client.dial(ctx);
dialed = true; dialed = true;
SessionToken token = initSessionForDuration(client, rebalanceParams.getSessionExpirationDuration()); SessionToken token = initSessionForDuration(
ctx, client, rebalanceParams.getSessionExpirationDuration()
);
String cacheKey = formCacheKey( String cacheKey = formCacheKey(
nodeParams.getAddress().get(j), nodeParams.getAddress().get(j),
getHexString(key.getPublicKeyByte()) getHexString(key.getPublicKeyByte())
@ -236,10 +251,10 @@ public class Pool implements CommonClient {
this.innerPools = inner; this.innerPools = inner;
NetworkSettings networkSettings = getNetworkSettings(); NetworkSettings networkSettings = getNetworkSettings(ctx);
this.maxObjectSize = networkSettings.getMaxObjectSize(); this.maxObjectSize = networkSettings.getMaxObjectSize();
startRebalance(); startRebalance(ctx);
return null; 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][]; double[][] buffers = new double[rebalanceParams.getNodesParams().length][];
for (int i = 0; i < rebalanceParams.getNodesParams().length; i++) { for (int i = 0; i < rebalanceParams.getNodesParams().length; i++) {
@ -276,24 +291,24 @@ public class Pool implements CommonClient {
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
WaitUtil.sleep(rebalanceParams.getClientRebalanceInterval()); 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]; CompletableFuture<?>[] tasks = new CompletableFuture<?>[innerPools.length];
for (int i = 0; i < innerPools.length; i++) { for (int i = 0; i < innerPools.length; i++) {
double[] bufferWeights = buffers[i]; double[] bufferWeights = buffers[i];
int finalI = i; int finalI = i;
tasks[i] = CompletableFuture.runAsync(() -> updateInnerNodesHealth(finalI, bufferWeights)); tasks[i] = CompletableFuture.runAsync(() -> updateInnerNodesHealth(ctx, finalI, bufferWeights));
} }
CompletableFuture.allOf(tasks).join(); 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) { if (poolIndex > innerPools.length - 1) {
return; return;
} }
@ -311,7 +326,7 @@ public class Pool implements CommonClient {
AtomicBoolean changed = new AtomicBoolean(false); AtomicBoolean changed = new AtomicBoolean(false);
int finalJ = j; int finalJ = j;
tasks[j] = client.restartIfUnhealthy().handle((unused, throwable) -> { tasks[j] = client.restartIfUnhealthy(ctx).handle((unused, throwable) -> {
if (throwable != null) { if (throwable != null) {
error.set(throwable.getMessage()); error.set(throwable.getMessage());
bufferWeights[finalJ] = 0; bufferWeights[finalJ] = 0;
@ -398,112 +413,112 @@ public class Pool implements CommonClient {
return statistics; return statistics;
} }
@Override @Override
public Container getContainer(ContainerId cid) { public Container getContainer(PrmContainerGet args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getContainer(cid); return client.getClient().getContainer(args, ctx);
} }
@Override @Override
public List<ContainerId> listContainers() { public List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().listContainers(); return client.getClient().listContainers(args, ctx);
} }
@Override @Override
public ContainerId createContainer(Container container) { public ContainerId createContainer(PrmContainerCreate args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().createContainer(container); return client.getClient().createContainer(args, ctx);
} }
@Override @Override
public void deleteContainer(ContainerId cid) { public void deleteContainer(PrmContainerDelete args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
client.getClient().deleteContainer(cid); client.getClient().deleteContainer(args, ctx);
} }
@Override @Override
public ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId) { public ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getObjectHead(containerId, objectId); return client.getClient().getObjectHead(args, ctx);
} }
@Override @Override
public ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId) { public ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getObject(containerId, objectId); return client.getClient().getObject(args, ctx);
} }
@Override @Override
public ObjectId putObject(PutObjectParameters parameters) { public ObjectWriter putObject(PrmObjectPut args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().putObject(parameters); return client.getClient().putObject(args, ctx);
} }
@Override @Override
public ObjectId putSingleObject(ObjectFrostFS objectFrostFS) { public ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().putSingleObject(objectFrostFS); return client.getClient().putClientCutObject(args, ctx);
} }
@Override @Override
public void deleteObject(ContainerId containerId, ObjectId objectId) { public ObjectId putSingleObject(PrmObjectSinglePut args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
client.getClient().deleteObject(containerId, objectId); return client.getClient().putSingleObject(args, ctx);
} }
@Override @Override
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) { public void deleteObject(PrmObjectDelete args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().searchObjects(cid, filters); client.getClient().deleteObject(args, ctx);
} }
@Override @Override
public byte[] addChain(Chain chain, ChainTarget chainTarget) { public Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().addChain(chain, chainTarget); return client.getClient().searchObjects(args, ctx);
} }
@Override @Override
public void removeChain(Chain chain, ChainTarget chainTarget) { public byte[] addChain(PrmApeChainAdd args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
client.getClient().removeChain(chain, chainTarget); return client.getClient().addChain(args, ctx);
} }
@Override @Override
public List<Chain> listChains(ChainTarget chainTarget) { public void removeChain(PrmApeChainRemove args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().listChains(chainTarget); client.getClient().removeChain(args, ctx);
} }
@Override @Override
public NetmapSnapshot getNetmapSnapshot() { public List<Chain> listChains(PrmApeChainList args, CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getNetmapSnapshot(); return client.getClient().listChains(args, ctx);
} }
@Override @Override
public NodeInfo getLocalNodeInfo() { public NetmapSnapshot getNetmapSnapshot(CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getLocalNodeInfo(); return client.getClient().getNetmapSnapshot(ctx);
} }
@Override @Override
public NetworkSettings getNetworkSettings() { public NodeInfo getLocalNodeInfo(CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getNetworkSettings(); return client.getClient().getLocalNodeInfo(ctx);
} }
@Override @Override
public SessionToken createSession(long expiration) { public NetworkSettings getNetworkSettings(CallContext ctx) {
ClientWrapper client = connection(); 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(); ClientWrapper client = connection();
return client.getClient().createSessionInternal(expiration); return client.getClient().createSession(args, ctx);
} }
@Override @Override
@ -513,8 +528,8 @@ public class Pool implements CommonClient {
} }
@Override @Override
public frostfs.accounting.Types.Decimal getBalance() { public frostfs.accounting.Types.Decimal getBalance(CallContext ctx) {
ClientWrapper client = connection(); ClientWrapper client = connection();
return client.getClient().getBalance(); return client.getClient().getBalance(ctx);
} }
} }

View file

@ -1,6 +1,7 @@
package info.frostfs.sdk.pool; package info.frostfs.sdk.pool;
import info.frostfs.sdk.dto.session.SessionToken; import info.frostfs.sdk.dto.session.SessionToken;
import org.apache.commons.lang3.StringUtils;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -18,18 +19,8 @@ public class SessionCache {
return cache.containsKey(key); return cache.containsKey(key);
} }
public boolean tryGetValue(String key, SessionToken[] value) { public SessionToken tryGetValue(String key) {
if (key == null) { return StringUtils.isBlank(key) ? null : cache.get(key);
value[0] = null;
return false;
}
SessionToken token = cache.get(key);
if (token != null) {
value[0] = token;
return true;
}
return false;
} }
public void setValue(String key, SessionToken value) { public void setValue(String key, SessionToken value) {

View file

@ -1,7 +1,8 @@
package info.frostfs.sdk.services; package info.frostfs.sdk.services;
import frostfs.accounting.Types; import frostfs.accounting.Types;
import info.frostfs.sdk.jdo.parameters.CallContext;
public interface AccountingClient { public interface AccountingClient {
Types.Decimal getBalance(); Types.Decimal getBalance(CallContext ctx);
} }

View file

@ -1,14 +1,17 @@
package info.frostfs.sdk.services; package info.frostfs.sdk.services;
import info.frostfs.sdk.dto.chain.Chain; 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; import java.util.List;
public interface ApeManagerClient { 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);
} }

View file

@ -2,15 +2,20 @@ package info.frostfs.sdk.services;
import info.frostfs.sdk.dto.container.Container; import info.frostfs.sdk.dto.container.Container;
import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.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; import java.util.List;
public interface ContainerClient { 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);
} }

View file

@ -3,11 +3,12 @@ package info.frostfs.sdk.services;
import info.frostfs.sdk.dto.netmap.NetmapSnapshot; import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
import info.frostfs.sdk.dto.netmap.NodeInfo; import info.frostfs.sdk.dto.netmap.NodeInfo;
import info.frostfs.sdk.jdo.NetworkSettings; import info.frostfs.sdk.jdo.NetworkSettings;
import info.frostfs.sdk.jdo.parameters.CallContext;
public interface NetmapClient { public interface NetmapClient {
NetmapSnapshot getNetmapSnapshot(); NetmapSnapshot getNetmapSnapshot(CallContext ctx);
NodeInfo getLocalNodeInfo(); NodeInfo getLocalNodeInfo(CallContext ctx);
NetworkSettings getNetworkSettings(); NetworkSettings getNetworkSettings(CallContext ctx);
} }

View file

@ -1,22 +1,24 @@
package info.frostfs.sdk.services; 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.ObjectFrostFS;
import info.frostfs.sdk.dto.object.ObjectHeader;
import info.frostfs.sdk.dto.object.ObjectId; import info.frostfs.sdk.dto.object.ObjectId;
import info.frostfs.sdk.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 { 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);
} }

View file

@ -1,7 +1,9 @@
package info.frostfs.sdk.services; package info.frostfs.sdk.services;
import info.frostfs.sdk.dto.session.SessionToken; 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 { public interface SessionClient {
SessionToken createSession(long expiration); SessionToken createSession(PrmSessionCreate args, CallContext ctx);
} }

View file

@ -1,9 +1,9 @@
package info.frostfs.sdk.services; package info.frostfs.sdk.services;
import frostfs.session.Types;
import info.frostfs.sdk.dto.session.SessionToken; import info.frostfs.sdk.dto.session.SessionToken;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.jdo.parameters.CallContext;
public interface SessionTools { public interface SessionTools {
Types.SessionToken getOrCreateSession(SessionToken token, ClientEnvironment env); SessionToken getOrCreateSession(ClientEnvironment env, CallContext ctx);
} }

View file

@ -4,6 +4,7 @@ import frostfs.accounting.AccountingServiceGrpc;
import frostfs.accounting.Service; import frostfs.accounting.Service;
import frostfs.accounting.Types; import frostfs.accounting.Types;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.jdo.parameters.CallContext;
import info.frostfs.sdk.mappers.object.OwnerIdMapper; import info.frostfs.sdk.mappers.object.OwnerIdMapper;
import info.frostfs.sdk.services.AccountingClient; import info.frostfs.sdk.services.AccountingClient;
import info.frostfs.sdk.services.ContextAccessor; 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.RequestSigner;
import info.frostfs.sdk.tools.Verifier; 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 { public class AccountingClientImpl extends ContextAccessor implements AccountingClient {
private final AccountingServiceGrpc.AccountingServiceBlockingStub serviceBlockingStub; private final AccountingServiceGrpc.AccountingServiceBlockingStub serviceBlockingStub;
@ -22,23 +23,24 @@ public class AccountingClientImpl extends ContextAccessor implements AccountingC
} }
@Override @Override
public Types.Decimal getBalance() { public Types.Decimal getBalance(CallContext ctx) {
var request = createGetRequest(null); var request = createGetRequest();
var response = serviceBlockingStub.balance(request); var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
var response = service.balance(request);
Verifier.checkResponse(response); Verifier.checkResponse(response);
return response.getBody().getBalance(); return response.getBody().getBalance();
} }
private Service.BalanceRequest createGetRequest(Map<String, String> xHeaders) { private Service.BalanceRequest createGetRequest() {
var body = Service.BalanceRequest.Body.newBuilder() var body = Service.BalanceRequest.Body.newBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.build(); .build();
var request = Service.BalanceRequest.newBuilder() var request = Service.BalanceRequest.newBuilder()
.setBody(body); .setBody(body);
RequestConstructor.addMetaHeader(request, xHeaders); RequestConstructor.addMetaHeader(request);
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); return request.build();

View file

@ -5,9 +5,11 @@ import frostfs.ape.Types;
import frostfs.apemanager.APEManagerServiceGrpc; import frostfs.apemanager.APEManagerServiceGrpc;
import frostfs.apemanager.Service; import frostfs.apemanager.Service;
import info.frostfs.sdk.dto.chain.Chain; 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.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.ChainMapper;
import info.frostfs.sdk.mappers.chain.ChainTargetMapper; import info.frostfs.sdk.mappers.chain.ChainTargetMapper;
import info.frostfs.sdk.services.ApeManagerClient; import info.frostfs.sdk.services.ApeManagerClient;
@ -17,10 +19,9 @@ import info.frostfs.sdk.tools.RequestSigner;
import info.frostfs.sdk.tools.Verifier; import info.frostfs.sdk.tools.Verifier;
import java.util.List; import java.util.List;
import java.util.Map;
import static info.frostfs.sdk.constants.ErrorConst.*; import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
import static java.util.Objects.isNull; import static info.frostfs.sdk.utils.Validator.validate;
public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerClient { public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerClient {
private final APEManagerServiceGrpc.APEManagerServiceBlockingStub apeManagerServiceClient; private final APEManagerServiceGrpc.APEManagerServiceBlockingStub apeManagerServiceClient;
@ -31,19 +32,13 @@ public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerC
} }
@Override @Override
public byte[] addChain(Chain chain, ChainTarget chainTarget) { public byte[] addChain(PrmApeChainAdd args, CallContext ctx) {
if (isNull(chain) || isNull(chainTarget)) { validate(args);
throw new ValidationFrostFSException(
String.format(
PARAMS_ARE_MISSING_TEMPLATE,
String.join(FIELDS_DELIMITER_COMMA, Chain.class.getName(), ChainTarget.class.getName())
)
);
}
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); Verifier.checkResponse(response);
@ -51,82 +46,70 @@ public class ApeManagerClientImpl extends ContextAccessor implements ApeManagerC
} }
@Override @Override
public void removeChain(Chain chain, ChainTarget chainTarget) { public void removeChain(PrmApeChainRemove args, CallContext ctx) {
if (isNull(chain) || isNull(chainTarget)) { validate(args);
throw new ValidationFrostFSException(
String.format(
PARAMS_ARE_MISSING_TEMPLATE,
String.join(FIELDS_DELIMITER_COMMA, Chain.class.getName(), ChainTarget.class.getName())
)
);
}
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); Verifier.checkResponse(response);
} }
@Override @Override
public List<Chain> listChains(ChainTarget chainTarget) { public List<Chain> listChains(PrmApeChainList args, CallContext ctx) {
if (isNull(chainTarget)) { validate(args);
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, ChainTarget.class.getName()));
}
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); Verifier.checkResponse(response);
return ChainMapper.toModels(response.getBody().getChainsList()); return ChainMapper.toModels(response.getBody().getChainsList());
} }
private Service.AddChainRequest createAddChainRequest(Chain chain, private Service.AddChainRequest createAddChainRequest(PrmApeChainAdd args) {
ChainTarget chainTarget,
Map<String, String> xHeaders) {
var chainGrpc = Types.Chain.newBuilder() var chainGrpc = Types.Chain.newBuilder()
.setRaw(ByteString.copyFrom(chain.getRaw())) .setRaw(ByteString.copyFrom(args.getChain().getRaw()))
.build(); .build();
var body = Service.AddChainRequest.Body.newBuilder() var body = Service.AddChainRequest.Body.newBuilder()
.setChain(chainGrpc) .setChain(chainGrpc)
.setTarget(ChainTargetMapper.toGrpcMessage(chainTarget)) .setTarget(ChainTargetMapper.toGrpcMessage(args.getChainTarget()))
.build(); .build();
var request = Service.AddChainRequest.newBuilder() var request = Service.AddChainRequest.newBuilder()
.setBody(body); .setBody(body);
RequestConstructor.addMetaHeader(request, xHeaders); RequestConstructor.addMetaHeader(request, args.getXHeaders());
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); return request.build();
} }
private Service.RemoveChainRequest createRemoveChainRequest(Chain chain, private Service.RemoveChainRequest createRemoveChainRequest(PrmApeChainRemove args) {
ChainTarget chainTarget,
Map<String, String> xHeaders) {
var body = Service.RemoveChainRequest.Body.newBuilder() var body = Service.RemoveChainRequest.Body.newBuilder()
.setChainId(ByteString.copyFrom(chain.getRaw())) .setChainId(ByteString.copyFrom(args.getChain().getRaw()))
.setTarget(ChainTargetMapper.toGrpcMessage(chainTarget)) .setTarget(ChainTargetMapper.toGrpcMessage(args.getChainTarget()))
.build(); .build();
var request = Service.RemoveChainRequest.newBuilder() var request = Service.RemoveChainRequest.newBuilder()
.setBody(body); .setBody(body);
RequestConstructor.addMetaHeader(request, xHeaders); RequestConstructor.addMetaHeader(request, args.getXHeaders());
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); return request.build();
} }
private Service.ListChainsRequest createListChainsRequest(ChainTarget chainTarget, private Service.ListChainsRequest createListChainsRequest(PrmApeChainList args) {
Map<String, String> xHeaders) {
var body = Service.ListChainsRequest.Body.newBuilder() var body = Service.ListChainsRequest.Body.newBuilder()
.setTarget(ChainTargetMapper.toGrpcMessage(chainTarget)) .setTarget(ChainTargetMapper.toGrpcMessage(args.getChainTarget()))
.build(); .build();
var request = Service.ListChainsRequest.newBuilder() var request = Service.ListChainsRequest.newBuilder()
.setBody(body); .setBody(body);
RequestConstructor.addMetaHeader(request, xHeaders); RequestConstructor.addMetaHeader(request, args.getXHeaders());
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); return request.build();

View file

@ -10,9 +10,14 @@ import info.frostfs.sdk.enums.StatusCode;
import info.frostfs.sdk.enums.WaitExpects; import info.frostfs.sdk.enums.WaitExpects;
import info.frostfs.sdk.exceptions.ResponseFrostFSException; import info.frostfs.sdk.exceptions.ResponseFrostFSException;
import info.frostfs.sdk.exceptions.TimeoutFrostFSException; import info.frostfs.sdk.exceptions.TimeoutFrostFSException;
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
import info.frostfs.sdk.jdo.ClientEnvironment; 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.ContainerIdMapper;
import info.frostfs.sdk.mappers.container.ContainerMapper; import info.frostfs.sdk.mappers.container.ContainerMapper;
import info.frostfs.sdk.mappers.netmap.VersionMapper; import info.frostfs.sdk.mappers.netmap.VersionMapper;
@ -29,8 +34,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; 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.isNull;
import static java.util.Objects.nonNull;
public class ContainerClientImpl extends ContextAccessor implements ContainerClient { public class ContainerClientImpl extends ContextAccessor implements ContainerClient {
private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub; private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub;
@ -42,29 +50,33 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
this.sessionTools = new SessionToolsImpl(clientEnvironment); this.sessionTools = new SessionToolsImpl(clientEnvironment);
} }
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) { public SessionToken getOrCreateSession(SessionContext sessionContext, CallContext ctx) {
return sessionTools.getOrCreateSession(sessionToken, getContext()); return isNull(sessionContext.getSessionToken())
? sessionTools.getOrCreateSession(getContext(), ctx)
: sessionContext.getSessionToken();
} }
@Override @Override
public Container getContainer(ContainerId cid) { public Container getContainer(PrmContainerGet args, CallContext ctx) {
if (isNull(cid)) { validate(args);
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, ContainerId.class.getName()));
}
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); Verifier.checkResponse(response);
return ContainerMapper.toModel(response.getBody().getContainer()); return ContainerMapper.toModel(response.getBody().getContainer());
} }
@Override @Override
public List<ContainerId> listContainers() { public List<ContainerId> listContainers(PrmContainerGetAll args, CallContext ctx) {
var request = createListRequest(null); 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); Verifier.checkResponse(response);
@ -74,43 +86,39 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
} }
@Override @Override
public ContainerId createContainer(Container container) { public ContainerId createContainer(PrmContainerCreate args, CallContext ctx) {
if (isNull(container)) { validate(args);
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, Container.class.getName()));
}
var grpcContainer = ContainerMapper.toGrpcMessage(container); var request = createPutRequest(args, ctx);
var request = createPutRequest(grpcContainer, null);
var response = serviceBlockingStub.put(request); var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
var response = service.put(request);
Verifier.checkResponse(response); 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()); return new ContainerId(response.getBody().getContainerId().getValue().toByteArray());
} }
@Override @Override
public void deleteContainer(ContainerId cid) { public void deleteContainer(PrmContainerDelete args, CallContext ctx) {
if (isNull(cid)) { validate(args);
throw new ValidationFrostFSException(String.format(PARAM_IS_MISSING_TEMPLATE, ContainerId.class.getName()));
}
var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid); var request = createDeleteRequest(args, ctx);
var request = createDeleteRequest(grpcContainerId, null);
var response = serviceBlockingStub.delete(request); var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
var response = service.delete(request);
Verifier.checkResponse(response); 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) { private void waitForContainer(WaitExpects expect, Types.ContainerID cid, PrmWait waitParams) {
var request = createGetRequest(id, null); var request = createGetRequest(cid, null);
waitParams = isNull(waitParams) ? new WaitParameters() : waitParams; waitParams = isNull(waitParams) ? new PrmWait() : waitParams;
var deadLine = waitParams.getDeadline(); var deadLine = waitParams.getDeadline();
while (true) { 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, private Service.GetRequest createGetRequest(Types.ContainerID cid, Map<String, String> xHeaders) {
Map<String, String> xHeaders) {
var body = Service.GetRequest.Body.newBuilder() var body = Service.GetRequest.Body.newBuilder()
.setContainerId(cid) .setContainerId(cid)
.build(); .build();
@ -160,22 +171,22 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
return request.build(); return request.build();
} }
private Service.ListRequest createListRequest(Map<String, String> xHeaders) { private Service.ListRequest createListRequest(PrmContainerGetAll args) {
var body = Service.ListRequest.Body.newBuilder() var body = Service.ListRequest.Body.newBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.build(); .build();
var request = Service.ListRequest.newBuilder() var request = Service.ListRequest.newBuilder()
.setBody(body); .setBody(body);
RequestConstructor.addMetaHeader(request, xHeaders); RequestConstructor.addMetaHeader(request, args.getXHeaders());
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); return request.build();
} }
private Service.PutRequest createPutRequest(frostfs.container.Types.Container container, private Service.PutRequest createPutRequest(PrmContainerCreate args, CallContext ctx) {
Map<String, String> xHeaders) { syncContainerWithNetwork(args.getContainer(), ctx);
container = container.toBuilder() var container = ContainerMapper.toGrpcMessage(args.getContainer()).toBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())) .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion()))
.build(); .build();
@ -187,9 +198,8 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
var request = Service.PutRequest.newBuilder() var request = Service.PutRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createContainerTokenContext(
sessionToken = RequestConstructor.createContainerTokenContext(
sessionToken, sessionToken,
null, null,
frostfs.session.Types.ContainerSessionContext.Verb.PUT, frostfs.session.Types.ContainerSessionContext.Verb.PUT,
@ -197,14 +207,15 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, xHeaders, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); return request.build();
} }
private Service.DeleteRequest createDeleteRequest(Types.ContainerID cid, private Service.DeleteRequest createDeleteRequest(PrmContainerDelete args, CallContext ctx) {
Map<String, String> xHeaders) { var cid = ContainerIdMapper.toGrpcMessage(args.getContainerId());
var body = Service.DeleteRequest.Body.newBuilder() var body = Service.DeleteRequest.Body.newBuilder()
.setContainerId(cid) .setContainerId(cid)
.setSignature(RequestSigner.signRFC6979(getContext().getKey(), cid.getValue())) .setSignature(RequestSigner.signRFC6979(getContext().getKey(), cid.getValue()))
@ -212,9 +223,8 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
var request = Service.DeleteRequest.newBuilder() var request = Service.DeleteRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createContainerTokenContext(
sessionToken = RequestConstructor.createContainerTokenContext(
sessionToken, sessionToken,
null, null,
frostfs.session.Types.ContainerSessionContext.Verb.DELETE, frostfs.session.Types.ContainerSessionContext.Verb.DELETE,
@ -222,9 +232,18 @@ public class ContainerClientImpl extends ContextAccessor implements ContainerCli
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, xHeaders, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
RequestSigner.sign(request, getContext().getKey()); RequestSigner.sign(request, getContext().getKey());
return request.build(); 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());
}
}
} }

View file

@ -7,6 +7,7 @@ import info.frostfs.sdk.dto.netmap.NetmapSnapshot;
import info.frostfs.sdk.dto.netmap.NodeInfo; import info.frostfs.sdk.dto.netmap.NodeInfo;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.jdo.NetworkSettings; 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.NetmapSnapshotMapper;
import info.frostfs.sdk.mappers.netmap.NodeInfoMapper; import info.frostfs.sdk.mappers.netmap.NodeInfoMapper;
import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.ContextAccessor;
@ -17,6 +18,7 @@ import info.frostfs.sdk.tools.Verifier;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import static info.frostfs.sdk.tools.RequestSigner.sign; import static info.frostfs.sdk.tools.RequestSigner.sign;
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
public class NetmapClientImpl extends ContextAccessor implements NetmapClient { public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
@ -94,12 +96,12 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
} }
@Override @Override
public NetworkSettings getNetworkSettings() { public NetworkSettings getNetworkSettings(CallContext ctx) {
if (nonNull(getContext().getNetworkSettings())) { if (nonNull(getContext().getNetworkSettings())) {
return getContext().getNetworkSettings(); return getContext().getNetworkSettings();
} }
var info = getNetworkInfo(); var info = getNetworkInfo(ctx);
var settings = new NetworkSettings(); var settings = new NetworkSettings();
@ -113,25 +115,28 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
} }
@Override @Override
public NodeInfo getLocalNodeInfo() { public NodeInfo getLocalNodeInfo(CallContext ctx) {
var request = Service.LocalNodeInfoRequest.newBuilder(); var request = Service.LocalNodeInfoRequest.newBuilder();
RequestConstructor.addMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); 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); Verifier.checkResponse(response);
return NodeInfoMapper.toModel(response.getBody()); return NodeInfoMapper.toModel(response.getBody());
} }
public Service.NetworkInfoResponse getNetworkInfo() { public Service.NetworkInfoResponse getNetworkInfo(CallContext ctx) {
var request = Service.NetworkInfoRequest.newBuilder(); var request = Service.NetworkInfoRequest.newBuilder();
RequestConstructor.addMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); 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); Verifier.checkResponse(response);
@ -139,13 +144,14 @@ public class NetmapClientImpl extends ContextAccessor implements NetmapClient {
} }
@Override @Override
public NetmapSnapshot getNetmapSnapshot() { public NetmapSnapshot getNetmapSnapshot(CallContext ctx) {
var request = Service.NetmapSnapshotRequest.newBuilder(); var request = Service.NetmapSnapshotRequest.newBuilder();
RequestConstructor.addMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); 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); Verifier.checkResponse(response);

View file

@ -6,29 +6,26 @@ import frostfs.object.ObjectServiceGrpc;
import frostfs.object.Service; import frostfs.object.Service;
import frostfs.refs.Types; import frostfs.refs.Types;
import info.frostfs.sdk.constants.AppConst; import info.frostfs.sdk.constants.AppConst;
import info.frostfs.sdk.dto.container.ContainerId;
import info.frostfs.sdk.dto.object.*; import info.frostfs.sdk.dto.object.*;
import info.frostfs.sdk.dto.session.SessionToken; import info.frostfs.sdk.dto.session.SessionToken;
import info.frostfs.sdk.enums.ObjectType; import info.frostfs.sdk.enums.ObjectType;
import info.frostfs.sdk.exceptions.ProcessFrostFSException; import info.frostfs.sdk.exceptions.ProcessFrostFSException;
import info.frostfs.sdk.exceptions.ValidationFrostFSException;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.jdo.PutObjectParameters;
import info.frostfs.sdk.jdo.PutObjectResult; 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.container.ContainerIdMapper;
import info.frostfs.sdk.mappers.object.ObjectFilterMapper; import info.frostfs.sdk.mappers.object.*;
import info.frostfs.sdk.mappers.object.ObjectFrostFSMapper;
import info.frostfs.sdk.mappers.object.ObjectHeaderMapper;
import info.frostfs.sdk.mappers.object.ObjectIdMapper;
import info.frostfs.sdk.mappers.session.SessionMapper;
import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.ContextAccessor;
import info.frostfs.sdk.services.ObjectClient; import info.frostfs.sdk.services.ObjectClient;
import info.frostfs.sdk.services.impl.rwhelper.ObjectReaderImpl; 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.ObjectWriter;
import info.frostfs.sdk.services.impl.rwhelper.SearchReader; import info.frostfs.sdk.services.impl.rwhelper.SearchReader;
import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestConstructor;
import info.frostfs.sdk.tools.Verifier; import info.frostfs.sdk.tools.Verifier;
import info.frostfs.sdk.utils.Validator;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import java.io.IOException; import java.io.IOException;
@ -37,9 +34,12 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import static info.frostfs.sdk.Helper.getSha256; import static info.frostfs.sdk.Helper.getSha256;
import static info.frostfs.sdk.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.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.isNull;
import static java.util.Objects.nonNull;
public class ObjectClientImpl extends ContextAccessor implements ObjectClient { public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
@ -55,87 +55,153 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
this.sessionTools = new SessionToolsImpl(clientEnvironment); this.sessionTools = new SessionToolsImpl(clientEnvironment);
} }
public frostfs.session.Types.SessionToken getOrCreateSession(SessionToken sessionToken) { public SessionToken getOrCreateSession(SessionContext sessionContext, CallContext ctx) {
return sessionTools.getOrCreateSession(sessionToken, getContext()); return isNull(sessionContext.getSessionToken())
? sessionTools.getOrCreateSession(getContext(), ctx)
: sessionContext.getSessionToken();
} }
@Override @Override
public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) { public ObjectHeaderResult getObjectHead(PrmObjectHeadGet args, CallContext ctx) {
if (isNull(cid) || isNull(oid)) { validate(args);
throw new ValidationFrostFSException(
String.format(
PARAMS_ARE_MISSING_TEMPLATE,
String.join(FIELDS_DELIMITER_COMMA, ContainerId.class.getName(), ObjectId.class.getName())
)
);
}
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); 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 @Override
public ObjectFrostFS getObject(ContainerId cid, ObjectId oid) { public ObjectFrostFS getObject(PrmObjectGet args, CallContext ctx) {
var request = createGetRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid)); validate(args);
return getObject(request); var request = createGetRequest(args, ctx);
return getObject(request, ctx);
} }
@Override @Override
public void deleteObject(ContainerId cid, ObjectId oid) { public void deleteObject(PrmObjectDelete args, CallContext ctx) {
var request = createDeleteRequest(ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid)); 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); Verifier.checkResponse(response);
} }
@Override @Override
public Iterable<ObjectId> searchObjects(ContainerId cid, ObjectFilter<?>... filters) { public Iterable<ObjectId> searchObjects(PrmObjectSearch args, CallContext ctx) {
var request = createSearchRequest(ContainerIdMapper.toGrpcMessage(cid), filters); 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())); return Iterables.transform(objectsIds, input -> new ObjectId(input.getValue().toByteArray()));
} }
@Override @Override
public ObjectId putObject(PutObjectParameters parameters) { public ObjectWriter putObject(PrmObjectPut args, CallContext ctx) {
Validator.validate(parameters); validate(args);
if (parameters.isClientCut()) { return new ObjectWriter(getContext(), args, getUploadStream(args, ctx));
return putClientCutObject(parameters);
}
if (parameters.getHeader().getPayloadLength() > 0) {
parameters.setFullLength(parameters.getHeader().getPayloadLength());
} else {
parameters.setFullLength(getStreamSize(parameters.getPayload()));
}
return putStreamObject(parameters).getObjectId();
} }
@Override @Override
public ObjectId putSingleObject(ObjectFrostFS modelObject) { public ObjectId putClientCutObject(PrmObjectClientCutPut args, CallContext ctx) {
var grpcObject = objectToolsImpl.createObject(modelObject); 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); Verifier.checkResponse(response);
return new ObjectId(grpcObject.getObjectId().getValue().toByteArray()); return new ObjectId(grpcObject.getObjectId().getValue().toByteArray());
} }
private ObjectFrostFS getObject(Service.GetRequest request) { private ObjectFrostFS getObject(Service.GetRequest request, CallContext ctx) {
var reader = getObjectInit(request); var reader = getObjectInit(request, ctx);
var grpcObject = reader.readHeader(); var grpcObject = reader.readHeader();
var modelObject = ObjectFrostFSMapper.toModel(grpcObject); var modelObject = ObjectFrostFSMapper.toModel(grpcObject);
@ -145,39 +211,41 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
return modelObject; return modelObject;
} }
private ObjectReaderImpl getObjectInit(Service.GetRequest initRequest) { private ObjectReaderImpl getObjectInit(Service.GetRequest initRequest, CallContext ctx) {
if (initRequest.getSerializedSize() == 0) { if (initRequest.getSerializedSize() == 0) {
throw new ProcessFrostFSException( throw new ProcessFrostFSException(
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, initRequest.getClass().getName()) 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) { private PutObjectResult putMultipartStreamObject(PrmObjectClientCutPut args, CallContext ctx) {
var chunkSize = parameters.getBufferMaxSize() > 0 ? parameters.getBufferMaxSize() : AppConst.OBJECT_CHUNK_SIZE; 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); chunkSize = (int) Math.min(restBytes, chunkSize);
byte[] chunkBuffer = parameters.getCustomerBuffer() != null byte[] chunkBuffer = args.getCustomerBuffer() != null
? parameters.getCustomerBuffer() ? args.getCustomerBuffer()
: new byte[chunkSize];//todo change to pool : new byte[chunkSize];//todo change to pool
var sentBytes = 0; var sentBytes = 0;
// 0 means no limit from client, so server side cut is performed // 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) { while (objectLimitSize == 0 || sentBytes < objectLimitSize) {
// send chunks limited to default or user's settings // send chunks limited to default or user's settings
var bufferSize = objectLimitSize > 0 ? Math.min(objectLimitSize - sentBytes, chunkSize) : chunkSize; 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) { if (bytesCount == 0) {
break; break;
@ -204,110 +272,40 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
return new PutObjectResult(objectId, sentBytes); return new PutObjectResult(objectId, sentBytes);
} }
private ObjectId putClientCutObject(PutObjectParameters parameters) { private ObjectStreamer getUploadStream(PrmObjectPutBase args, CallContext ctx) {
var header = parameters.getHeader(); var header = args.getObjectHeader();
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();
header.setOwnerId(getContext().getOwnerId()); header.setOwnerId(getContext().getOwnerId());
header.setVersion(getContext().getVersion()); header.setVersion(getContext().getVersion());
var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header); var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header);
if (nonNull(header.getSplit())) {
grpcHeader = objectToolsImpl.updateSplitValues(grpcHeader, header.getSplit()); grpcHeader = objectToolsImpl.updateSplitValues(grpcHeader, header.getSplit());
}
var oid = Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build(); 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) { if (initRequest.getSerializedSize() == 0) {
throw new ProcessFrostFSException( throw new ProcessFrostFSException(
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, initRequest.getClass().getName()) 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); writer.write(initRequest);
return writer; return writer;
} }
private Iterable<Types.ObjectID> searchObjects(Service.SearchRequest request) { private Iterable<Types.ObjectID> searchObjects(Service.SearchRequest request, CallContext ctx) {
var reader = getSearchReader(request); var reader = getSearchReader(request, ctx);
var ids = reader.read(); var ids = reader.read();
List<Types.ObjectID> result = new ArrayList<>(); List<Types.ObjectID> result = new ArrayList<>();
@ -319,14 +317,15 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
return result;//todo return yield return result;//todo return yield
} }
private SearchReader getSearchReader(Service.SearchRequest initRequest) { private SearchReader getSearchReader(Service.SearchRequest initRequest, CallContext ctx) {
if (initRequest.getSerializedSize() == 0) { if (initRequest.getSerializedSize() == 0) {
throw new ProcessFrostFSException( throw new ProcessFrostFSException(
String.format(PROTO_MESSAGE_IS_EMPTY_TEMPLATE, initRequest.getClass().getName()) 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) { 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() var address = Types.Address.newBuilder()
.setContainerId(cid) .setContainerId(ContainerIdMapper.toGrpcMessage(args.getContainerId()))
.setObjectId(oid) .setObjectId(ObjectIdMapper.toGrpcMessage(args.getObjectId()))
.build(); .build();
var body = Service.HeadRequest.Body.newBuilder() var body = Service.HeadRequest.Body.newBuilder()
.setAddress(address) .setAddress(address)
.setRaw(args.isRaw())
.build(); .build();
var request = Service.HeadRequest.newBuilder() var request = Service.HeadRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createObjectTokenContext(
sessionToken = RequestConstructor.createObjectTokenContext(
sessionToken, sessionToken,
address, address,
frostfs.session.Types.ObjectSessionContext.Verb.HEAD, frostfs.session.Types.ObjectSessionContext.Verb.HEAD,
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, null, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return request.build(); 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() var address = Types.Address.newBuilder()
.setContainerId(cid) .setContainerId(ContainerIdMapper.toGrpcMessage(args.getContainerId()))
.setObjectId(oid) .setObjectId(ObjectIdMapper.toGrpcMessage(args.getObjectId()))
.build(); .build();
var body = Service.GetRequest.Body.newBuilder() var body = Service.GetRequest.Body.newBuilder()
.setAddress(address) .setAddress(address)
@ -382,25 +382,24 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
var request = Service.GetRequest.newBuilder() var request = Service.GetRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createObjectTokenContext(
sessionToken = RequestConstructor.createObjectTokenContext(
sessionToken, sessionToken,
address, address,
frostfs.session.Types.ObjectSessionContext.Verb.GET, frostfs.session.Types.ObjectSessionContext.Verb.GET,
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, null, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return request.build(); 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() var address = Types.Address.newBuilder()
.setContainerId(cid) .setContainerId(ContainerIdMapper.toGrpcMessage(args.getContainerId()))
.setObjectId(oid) .setObjectId(ObjectIdMapper.toGrpcMessage(args.getObjectId()))
.build(); .build();
var body = Service.DeleteRequest.Body.newBuilder() var body = Service.DeleteRequest.Body.newBuilder()
.setAddress(address) .setAddress(address)
@ -408,22 +407,23 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
var request = Service.DeleteRequest.newBuilder() var request = Service.DeleteRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createObjectTokenContext(
sessionToken = RequestConstructor.createObjectTokenContext(
sessionToken, sessionToken,
address, address,
frostfs.session.Types.ObjectSessionContext.Verb.DELETE, frostfs.session.Types.ObjectSessionContext.Verb.DELETE,
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, null, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return request.build(); 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() var address = Types.Address.newBuilder()
.setContainerId(cid) .setContainerId(cid)
.build(); .build();
@ -432,29 +432,31 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
.setContainerId(cid) .setContainerId(cid)
.setVersion(1);// TODO: clarify this param .setVersion(1);// TODO: clarify this param
for (ObjectFilter<?> filter : filters) { for (ObjectFilter<?> filter : args.getFilters()) {
body.addFilters(ObjectFilterMapper.toGrpcMessage(filter)); body.addFilters(ObjectFilterMapper.toGrpcMessage(filter));
} }
var request = Service.SearchRequest.newBuilder() var request = Service.SearchRequest.newBuilder()
.setBody(body.build()); .setBody(body.build());
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createObjectTokenContext(
sessionToken = RequestConstructor.createObjectTokenContext(
sessionToken, sessionToken,
address, address,
frostfs.session.Types.ObjectSessionContext.Verb.SEARCH, frostfs.session.Types.ObjectSessionContext.Verb.SEARCH,
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, null, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return request.build(); 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() var address = Types.Address.newBuilder()
.setContainerId(header.getContainerId()) .setContainerId(header.getContainerId())
.setObjectId(oid) .setObjectId(oid)
@ -468,22 +470,23 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
var request = Service.PutRequest.newBuilder() var request = Service.PutRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createObjectTokenContext(
sessionToken = RequestConstructor.createObjectTokenContext(
sessionToken, sessionToken,
address, address,
frostfs.session.Types.ObjectSessionContext.Verb.PUT, frostfs.session.Types.ObjectSessionContext.Verb.PUT,
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, null, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return request.build(); 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() var address = Types.Address.newBuilder()
.setContainerId(grpcObject.getHeader().getContainerId()) .setContainerId(grpcObject.getHeader().getContainerId())
.setObjectId(grpcObject.getObjectId()) .setObjectId(grpcObject.getObjectId())
@ -494,16 +497,15 @@ public class ObjectClientImpl extends ContextAccessor implements ObjectClient {
var request = Service.PutSingleRequest.newBuilder() var request = Service.PutSingleRequest.newBuilder()
.setBody(body); .setBody(body);
var sessionToken = getOrCreateSession(null); var sessionToken = getOrCreateSession(args, ctx);
var protoToken = RequestConstructor.createObjectTokenContext(
sessionToken = RequestConstructor.createObjectTokenContext(
sessionToken, sessionToken,
address, address,
frostfs.session.Types.ObjectSessionContext.Verb.PUT, frostfs.session.Types.ObjectSessionContext.Verb.PUT,
getContext().getKey() getContext().getKey()
); );
RequestConstructor.addMetaHeader(request, null, sessionToken); RequestConstructor.addMetaHeader(request, args.getXHeaders(), protoToken);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return request.build(); return request.build();

View file

@ -5,6 +5,8 @@ import frostfs.session.SessionServiceGrpc;
import frostfs.session.Types; import frostfs.session.Types;
import info.frostfs.sdk.dto.session.SessionToken; import info.frostfs.sdk.dto.session.SessionToken;
import info.frostfs.sdk.jdo.ClientEnvironment; 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.object.OwnerIdMapper;
import info.frostfs.sdk.mappers.session.SessionMapper; import info.frostfs.sdk.mappers.session.SessionMapper;
import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.ContextAccessor;
@ -13,6 +15,7 @@ import info.frostfs.sdk.tools.RequestConstructor;
import info.frostfs.sdk.tools.Verifier; import info.frostfs.sdk.tools.Verifier;
import static info.frostfs.sdk.tools.RequestSigner.sign; import static info.frostfs.sdk.tools.RequestSigner.sign;
import static info.frostfs.sdk.utils.DeadLineUtil.deadLineAfter;
public class SessionClientImpl extends ContextAccessor implements SessionClient { public class SessionClientImpl extends ContextAccessor implements SessionClient {
private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub; private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub;
@ -23,16 +26,16 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
} }
@Override @Override
public SessionToken createSession(long expiration) { public SessionToken createSession(PrmSessionCreate args, CallContext ctx) {
var sessionToken = createSessionInternal(expiration); var sessionToken = createSessionInternal(args, ctx);
var token = SessionMapper.serialize(sessionToken); var token = SessionMapper.serialize(sessionToken);
return new SessionToken(token); return new SessionToken(token);
} }
public Types.SessionToken createSessionInternal(long expiration) { public Types.SessionToken createSessionInternal(PrmSessionCreate args, CallContext ctx) {
var body = Service.CreateRequest.Body.newBuilder() var body = Service.CreateRequest.Body.newBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId()))
.setExpiration(expiration) .setExpiration(args.getExpiration())
.build(); .build();
var request = Service.CreateRequest.newBuilder() var request = Service.CreateRequest.newBuilder()
.setBody(body); .setBody(body);
@ -40,11 +43,12 @@ public class SessionClientImpl extends ContextAccessor implements SessionClient
RequestConstructor.addMetaHeader(request); RequestConstructor.addMetaHeader(request);
sign(request, getContext().getKey()); sign(request, getContext().getKey());
return createSession(request.build()); return createSession(request.build(), ctx);
} }
private Types.SessionToken createSession(Service.CreateRequest request) { private Types.SessionToken createSession(Service.CreateRequest request, CallContext ctx) {
var response = serviceBlockingStub.create(request); var service = deadLineAfter(serviceBlockingStub, ctx.getTimeout(), ctx.getTimeUnit());
var response = service.create(request);
Verifier.checkResponse(response); Verifier.checkResponse(response);

View file

@ -1,12 +1,14 @@
package info.frostfs.sdk.services.impl; package info.frostfs.sdk.services.impl;
import frostfs.session.Types;
import info.frostfs.sdk.dto.session.SessionToken; import info.frostfs.sdk.dto.session.SessionToken;
import info.frostfs.sdk.exceptions.FrostFSException;
import info.frostfs.sdk.jdo.ClientEnvironment; 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.ContextAccessor;
import info.frostfs.sdk.services.SessionTools; import info.frostfs.sdk.services.SessionTools;
import static info.frostfs.sdk.constants.ErrorConst.SESSION_CREATE_FAILED;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
public class SessionToolsImpl extends ContextAccessor implements SessionTools { public class SessionToolsImpl extends ContextAccessor implements SessionTools {
@ -16,11 +18,18 @@ public class SessionToolsImpl extends ContextAccessor implements SessionTools {
} }
@Override @Override
public Types.SessionToken getOrCreateSession(SessionToken sessionToken, ClientEnvironment env) { public SessionToken getOrCreateSession(ClientEnvironment env, CallContext ctx) {
if (isNull(sessionToken)) { var token = env.getSessionCache().tryGetValue(env.getSessionKey());
return env.getFrostFSClient().createSessionInternal(-1);
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;
} }
} }

View file

@ -2,9 +2,11 @@ package info.frostfs.sdk.services.impl.interceptor;
import io.prometheus.client.CollectorRegistry; import io.prometheus.client.CollectorRegistry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class Configuration { public class Configuration {
private static final double[] DEFAULT_LATENCY_BUCKETS = private static final double[] DEFAULT_LATENCY_BUCKETS =
new double[]{.001, .005, .01, .05, 0.075, .1, .25, .5, 1, 2, 5, 10}; 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 double[] latencyBuckets;
private final List<String> labelHeaders; private final List<String> labelHeaders;
private final boolean isAddCodeLabelToHistograms; private final boolean isAddCodeLabelToHistograms;
private Configuration( private Configuration(
boolean isIncludeLatencyHistograms, boolean isIncludeLatencyHistograms,
CollectorRegistry collectorRegistry, 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() { public static Configuration cheapMetricsOnly() {
return new Configuration( return new Configuration(
false /* isIncludeLatencyHistograms */, false /* isIncludeLatencyHistograms */,
@ -119,27 +124,37 @@ public class Configuration {
true /* isAddCodeLabelToHistograms */); 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() { public boolean isIncludeLatencyHistograms() {
return isIncludeLatencyHistograms; return isIncludeLatencyHistograms;
} }
/** Returns the {@link CollectorRegistry} used to record stats. */ /**
* Returns the {@link CollectorRegistry} used to record stats.
*/
public CollectorRegistry getCollectorRegistry() { public CollectorRegistry getCollectorRegistry() {
return collectorRegistry; return collectorRegistry;
} }
/** Returns the histogram buckets to use for latency metrics. */ /**
* Returns the histogram buckets to use for latency metrics.
*/
public double[] getLatencyBuckets() { public double[] getLatencyBuckets() {
return latencyBuckets; 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() { public List<String> getLabelHeaders() {
return labelHeaders; 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() { public boolean isAddCodeLabelToHistograms() {
return isAddCodeLabelToHistograms; return isAddCodeLabelToHistograms;
} }

View file

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

View file

@ -1,63 +1,41 @@
package info.frostfs.sdk.services.impl.rwhelper; package info.frostfs.sdk.services.impl.rwhelper;
import frostfs.object.ObjectServiceGrpc; import com.google.protobuf.ByteString;
import frostfs.object.Service; import frostfs.object.Service;
import info.frostfs.sdk.exceptions.ProcessFrostFSException; import info.frostfs.sdk.dto.object.ObjectId;
import info.frostfs.sdk.utils.WaitUtil; import info.frostfs.sdk.jdo.ClientEnvironment;
import io.grpc.stub.StreamObserver; import info.frostfs.sdk.jdo.parameters.object.PrmObjectPutBase;
import info.frostfs.sdk.tools.Verifier;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import static info.frostfs.sdk.constants.ErrorConst.PROTO_MESSAGE_IS_EMPTY_TEMPLATE; import static info.frostfs.sdk.tools.RequestSigner.sign;
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();
}
//todo specify a deadline for each stream request, not for the entire stream
@Getter @Getter
private static class PutResponseCallback implements StreamObserver<Service.PutResponse> { @AllArgsConstructor
private Service.PutResponse response; public class ObjectWriter {
private final ClientEnvironment environment;
private final PrmObjectPutBase args;
private final ObjectStreamer streamer;
@Override public void write(byte[] buffer) {
public void onNext(Service.PutResponse putResponse) { var body = Service.PutRequest.Body.newBuilder()
this.response = putResponse; .setChunk(ByteString.copyFrom(buffer))
.build();
var chunkRequest = Service.PutRequest.newBuilder()
.setBody(body)
.clearVerifyHeader();
sign(chunkRequest, environment.getKey());
streamer.write(chunkRequest.build());
} }
@Override public ObjectId complete() {
public void onError(Throwable throwable) { var response = streamer.complete();
throw new ProcessFrostFSException(throwable); Verifier.checkResponse(response);
}
@Override return new ObjectId(response.getBody().getObjectId().getValue().toByteArray());
public void onCompleted() {
}
} }
} }

View file

@ -4,9 +4,11 @@ import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import frostfs.session.Types; import frostfs.session.Types;
import info.frostfs.sdk.dto.response.MetaHeader; import info.frostfs.sdk.dto.response.MetaHeader;
import info.frostfs.sdk.dto.session.SessionToken;
import info.frostfs.sdk.exceptions.ValidationFrostFSException; import info.frostfs.sdk.exceptions.ValidationFrostFSException;
import info.frostfs.sdk.jdo.ECDsa; import info.frostfs.sdk.jdo.ECDsa;
import info.frostfs.sdk.mappers.response.MetaHeaderMapper; import info.frostfs.sdk.mappers.response.MetaHeaderMapper;
import info.frostfs.sdk.mappers.session.SessionMapper;
import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MapUtils;
import java.util.Map; import java.util.Map;
@ -65,13 +67,11 @@ public class RequestConstructor {
setField(request, META_HEADER_FIELD_NAME, metaHeader.build()); 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, frostfs.refs.Types.Address address,
Types.ObjectSessionContext.Verb verb, Types.ObjectSessionContext.Verb verb,
ECDsa key) { ECDsa key) {
if (isNull(sessionToken) || sessionToken.getBody().getObject().getTarget().getSerializedSize() > 0) { var protoToken = SessionMapper.deserializeSessionToken(sessionToken.getToken());
return sessionToken;
}
var target = Types.ObjectSessionContext.Target.newBuilder() var target = Types.ObjectSessionContext.Target.newBuilder()
.setContainer(address.getContainerId()); .setContainer(address.getContainerId());
@ -84,25 +84,23 @@ public class RequestConstructor {
.setTarget(target.build()) .setTarget(target.build())
.setVerb(verb) .setVerb(verb)
.build(); .build();
var body = sessionToken.getBody().toBuilder() var body = protoToken.getBody().toBuilder()
.setObject(ctx) .setObject(ctx)
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte())) .setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()))
.build(); .build();
return sessionToken.toBuilder() return protoToken.toBuilder()
.setSignature(signMessagePart(key, body)) .setSignature(signMessagePart(key, body))
.setBody(body) .setBody(body)
.build(); .build();
} }
public static Types.SessionToken createContainerTokenContext(Types.SessionToken sessionToken, public static Types.SessionToken createContainerTokenContext(SessionToken sessionToken,
frostfs.refs.Types.ContainerID containerId, frostfs.refs.Types.ContainerID containerId,
Types.ContainerSessionContext.Verb verb, Types.ContainerSessionContext.Verb verb,
frostfs.refs.Types.OwnerID ownerId, frostfs.refs.Types.OwnerID ownerId,
ECDsa key) { ECDsa key) {
if (isNull(sessionToken) || sessionToken.getBody().getContainer().getContainerId().getSerializedSize() > 0) { var protoToken = SessionMapper.deserializeSessionToken(sessionToken.getToken());
return sessionToken;
}
var containerSession = Types.ContainerSessionContext.newBuilder().setVerb(verb); var containerSession = Types.ContainerSessionContext.newBuilder().setVerb(verb);
@ -112,7 +110,7 @@ public class RequestConstructor {
containerSession.setContainerId(containerId); containerSession.setContainerId(containerId);
} }
var bodyBuilder = sessionToken.getBody().toBuilder() var bodyBuilder = protoToken.getBody().toBuilder()
.setContainer(containerSession) .setContainer(containerSession)
.setSessionKey(ByteString.copyFrom(key.getPublicKeyByte())); .setSessionKey(ByteString.copyFrom(key.getPublicKeyByte()));
@ -122,7 +120,7 @@ public class RequestConstructor {
var body = bodyBuilder.build(); var body = bodyBuilder.build();
return sessionToken.toBuilder() return protoToken.toBuilder()
.setSignature(signMessagePart(key, body)) .setSignature(signMessagePart(key, body))
.setBody(body) .setBody(body)
.build(); .build();

View file

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

View file

@ -5,6 +5,7 @@ import frostfs.accounting.Service;
import info.frostfs.sdk.Base58; import info.frostfs.sdk.Base58;
import info.frostfs.sdk.dto.object.OwnerId; import info.frostfs.sdk.dto.object.OwnerId;
import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientEnvironment;
import info.frostfs.sdk.jdo.parameters.CallContext;
import info.frostfs.sdk.services.impl.AccountingClientImpl; import info.frostfs.sdk.services.impl.AccountingClientImpl;
import info.frostfs.sdk.testgenerator.AccountingGenerator; import info.frostfs.sdk.testgenerator.AccountingGenerator;
import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestConstructor;
@ -81,11 +82,11 @@ class AccountingClientTest {
when(AccountingServiceClient.balance(captor.capture())).thenReturn(response); when(AccountingServiceClient.balance(captor.capture())).thenReturn(response);
//When //When
var result = accountingClient.getBalance(); var result = accountingClient.getBalance(new CallContext(0, null));
//Then //Then
requestConstructorMock.verify( requestConstructorMock.verify(
() -> RequestConstructor.addMetaHeader(any(Service.BalanceRequest.Builder.class), eq(null)), () -> RequestConstructor.addMetaHeader(any(Service.BalanceRequest.Builder.class)),
times(1) times(1)
); );
requestSignerMock.verify( requestSignerMock.verify(

View file

@ -8,6 +8,10 @@ import info.frostfs.sdk.dto.chain.ChainTarget;
import info.frostfs.sdk.enums.TargetType; import info.frostfs.sdk.enums.TargetType;
import info.frostfs.sdk.exceptions.ValidationFrostFSException; import info.frostfs.sdk.exceptions.ValidationFrostFSException;
import info.frostfs.sdk.jdo.ClientEnvironment; 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.services.impl.ApeManagerClientImpl;
import info.frostfs.sdk.testgenerator.ApeManagerGenerator; import info.frostfs.sdk.testgenerator.ApeManagerGenerator;
import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestConstructor;
@ -78,6 +82,7 @@ class ApeManagerClientTest {
//Given //Given
Chain chain = generateChain(); Chain chain = generateChain();
ChainTarget chainTarget = generateChainTarget(); ChainTarget chainTarget = generateChainTarget();
PrmApeChainAdd params = new PrmApeChainAdd(chain, chainTarget);
var response = ApeManagerGenerator.generateAddChainResponse(); var response = ApeManagerGenerator.generateAddChainResponse();
@ -86,7 +91,7 @@ class ApeManagerClientTest {
when(apeManagerServiceClient.addChain(captor.capture())).thenReturn(response); when(apeManagerServiceClient.addChain(captor.capture())).thenReturn(response);
//When //When
var result = apeManagerClient.addChain(chain, chainTarget); var result = apeManagerClient.addChain(params, new CallContext(0, null));
//Then //Then
requestConstructorMock.verify( requestConstructorMock.verify(
@ -112,11 +117,15 @@ class ApeManagerClientTest {
//Given //Given
Chain chain = generateChain(); Chain chain = generateChain();
ChainTarget chainTarget = generateChainTarget(); ChainTarget chainTarget = generateChainTarget();
PrmApeChainAdd params1 = new PrmApeChainAdd(null, chainTarget);
PrmApeChainAdd params2 = new PrmApeChainAdd(chain, null);
PrmApeChainAdd params3 = new PrmApeChainAdd(null, null);
//When + Then //When + Then
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(null, chainTarget)); assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(params1, new CallContext()));
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(chain, null)); assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(params2, new CallContext()));
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(null, null)); assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.addChain(params3, new CallContext()));
} }
@Test @Test
@ -124,6 +133,7 @@ class ApeManagerClientTest {
//Given //Given
Chain chain = generateChain(); Chain chain = generateChain();
ChainTarget chainTarget = generateChainTarget(); ChainTarget chainTarget = generateChainTarget();
PrmApeChainRemove params = new PrmApeChainRemove(chain, chainTarget);
var response = ApeManagerGenerator.generateRemoveChainResponse(); var response = ApeManagerGenerator.generateRemoveChainResponse();
@ -132,7 +142,7 @@ class ApeManagerClientTest {
when(apeManagerServiceClient.removeChain(captor.capture())).thenReturn(response); when(apeManagerServiceClient.removeChain(captor.capture())).thenReturn(response);
//When //When
apeManagerClient.removeChain(chain, chainTarget); apeManagerClient.removeChain(params, new CallContext(0, null));
//Then //Then
requestConstructorMock.verify( requestConstructorMock.verify(
@ -156,17 +166,21 @@ class ApeManagerClientTest {
//Given //Given
Chain chain = generateChain(); Chain chain = generateChain();
ChainTarget chainTarget = generateChainTarget(); ChainTarget chainTarget = generateChainTarget();
PrmApeChainRemove params1 = new PrmApeChainRemove(null, chainTarget);
PrmApeChainRemove params2 = new PrmApeChainRemove(chain, null);
PrmApeChainRemove params3 = new PrmApeChainRemove(null, null);
//When + Then //When + Then
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(null, chainTarget)); assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(params1, new CallContext()));
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(chain, null)); assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(params2, new CallContext()));
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(null, null)); assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.removeChain(params3, new CallContext()));
} }
@Test @Test
void listChain_success() { void listChain_success() {
//Given //Given
ChainTarget chainTarget = generateChainTarget(); ChainTarget chainTarget = generateChainTarget();
PrmApeChainList params = new PrmApeChainList(chainTarget);
var response = ApeManagerGenerator.generateListChainsResponse(); var response = ApeManagerGenerator.generateListChainsResponse();
@ -175,7 +189,7 @@ class ApeManagerClientTest {
when(apeManagerServiceClient.listChains(captor.capture())).thenReturn(response); when(apeManagerServiceClient.listChains(captor.capture())).thenReturn(response);
//When //When
var result = apeManagerClient.listChains(chainTarget); var result = apeManagerClient.listChains(params, new CallContext(0, null));
//Then //Then
requestConstructorMock.verify( requestConstructorMock.verify(
@ -202,7 +216,8 @@ class ApeManagerClientTest {
@Test @Test
void listChain_wrongParams() { void listChain_wrongParams() {
//When + Then //When + Then
assertThrows(ValidationFrostFSException.class, () -> apeManagerClient.listChains(null)); assertThrows(ValidationFrostFSException.class,
() -> apeManagerClient.listChains(new PrmApeChainList(null), new CallContext()));
} }
private Chain generateChain() { private Chain generateChain() {

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>frostfs-sdk-java</artifactId> <artifactId>frostfs-sdk-java</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</parent> </parent>
<artifactId>cryptography</artifactId> <artifactId>cryptography</artifactId>
@ -21,7 +21,7 @@
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>exceptions</artifactId> <artifactId>exceptions</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>frostfs-sdk-java</artifactId> <artifactId>frostfs-sdk-java</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</parent> </parent>
<artifactId>exceptions</artifactId> <artifactId>exceptions</artifactId>

View file

@ -46,6 +46,8 @@ public class ErrorConst {
public static final String POOL_CLIENTS_UNHEALTHY = "cannot find alive client"; 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 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_COMMA = ", ";
public static final String FIELDS_DELIMITER_OR = " or "; public static final String FIELDS_DELIMITER_OR = " or ";

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>frostfs-sdk-java</artifactId> <artifactId>frostfs-sdk-java</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</parent> </parent>
<artifactId>models</artifactId> <artifactId>models</artifactId>
@ -21,17 +21,17 @@
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>cryptography</artifactId> <artifactId>cryptography</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>protos</artifactId> <artifactId>protos</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>exceptions</artifactId> <artifactId>exceptions</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</dependency> </dependency>
</dependencies> </dependencies>

View file

@ -12,6 +12,7 @@ public class AppConst {
public static final int OBJECT_CHUNK_SIZE = 3 * MIB; public static final int OBJECT_CHUNK_SIZE = 3 * MIB;
public static final int SHA256_HASH_LENGTH = 32; public static final int SHA256_HASH_LENGTH = 32;
public static final int UUID_BYTE_ARRAY_LENGTH = 16; public static final int UUID_BYTE_ARRAY_LENGTH = 16;
public static final int DEFAULT_GRPC_TIMEOUT = 5;
private AppConst() { private AppConst() {
} }

View file

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

View file

@ -13,7 +13,6 @@ import java.util.stream.Collectors;
import static info.frostfs.sdk.UuidExtension.asBytes; import static info.frostfs.sdk.UuidExtension.asBytes;
import static info.frostfs.sdk.UuidExtension.asUuid; import static info.frostfs.sdk.UuidExtension.asUuid;
import static info.frostfs.sdk.constants.AttributeConst.DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE;
import static info.frostfs.sdk.constants.ErrorConst.UNKNOWN_ENUM_VALUE_TEMPLATE; import static info.frostfs.sdk.constants.ErrorConst.UNKNOWN_ENUM_VALUE_TEMPLATE;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
@ -31,7 +30,6 @@ public class ContainerMapper {
.setPlacementPolicy(PlacementPolicyMapper.toGrpcMessage(container.getPlacementPolicy())) .setPlacementPolicy(PlacementPolicyMapper.toGrpcMessage(container.getPlacementPolicy()))
.setNonce(ByteString.copyFrom(asBytes(container.getNonce()))); .setNonce(ByteString.copyFrom(asBytes(container.getNonce())));
container.getAttributes().putIfAbsent(DISABLE_HOMOMORPHIC_HASHING_ATTRIBUTE, Boolean.TRUE.toString());
var attributes = container.getAttributes().entrySet().stream() var attributes = container.getAttributes().entrySet().stream()
.map(entry -> .map(entry ->
Types.Container.Attribute.newBuilder() Types.Container.Attribute.newBuilder()

View file

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

View file

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

View file

@ -6,7 +6,7 @@
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>frostfs-sdk-java</artifactId> <artifactId>frostfs-sdk-java</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>
<module>client</module> <module>client</module>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>info.frostfs.sdk</groupId> <groupId>info.frostfs.sdk</groupId>
<artifactId>frostfs-sdk-java</artifactId> <artifactId>frostfs-sdk-java</artifactId>
<version>0.2.0</version> <version>0.3.0</version>
</parent> </parent>
<artifactId>protos</artifactId> <artifactId>protos</artifactId>