[#1] Refactor client structure

add session logic
add network logic
Signed-off-by: Ori Bruk <o.bruk@yadro.com>
This commit is contained in:
Ori Bruk 2024-07-16 15:00:17 +03:00
parent 2481774545
commit dc0eef770c
26 changed files with 868 additions and 302 deletions

View file

@ -25,7 +25,7 @@ import info.FrostFS.sdk.enums.BasicAcl;
import info.FrostFS.sdk.jdo.Container;
import info.FrostFS.sdk.jdo.netmap.PlacementPolicy;
import info.FrostFS.sdk.jdo.netmap.Replica;
import info.FrostFS.sdk.services.impl.FrostFSClient;
import info.FrostFS.sdk.services.FrostFSClient;
public class ContainerExample {
@ -58,7 +58,7 @@ import info.FrostFS.sdk.jdo.ContainerId;
import info.FrostFS.sdk.jdo.ObjectAttribute;
import info.FrostFS.sdk.jdo.ObjectFilter;
import info.FrostFS.sdk.jdo.ObjectHeader;
import info.FrostFS.sdk.services.impl.FrostFSClient;
import info.FrostFS.sdk.services.FrostFSClient;
import java.io.FileInputStream;
import java.io.IOException;

View file

@ -23,26 +23,11 @@
<artifactId>cryptography</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>info.FrostFS.sdk</groupId>
<artifactId>protosV2</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>info.FrostFS.sdk</groupId>
<artifactId>modelsV2</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
</project>

View file

@ -1,36 +0,0 @@
package info.FrostFS.sdk;
import info.FrostFS.sdk.jdo.OwnerId;
import info.FrostFS.sdk.jdo.Version;
import static info.FrostFS.sdk.KeyExtension.getPrivateKeyFromWIF;
import static info.FrostFS.sdk.KeyExtension.loadPublicKey;
public class Client {
private final OwnerId ownerId;
private final Version version = new Version(2, 13);
private final byte[] privateKey;
private final byte[] publicKey;
public Client(String key) {
this.privateKey = getPrivateKeyFromWIF(key);
this.publicKey = loadPublicKey(privateKey);
this.ownerId = OwnerId.fromKey(publicKey);
}
public OwnerId getOwnerId() {
return ownerId;
}
public Version getVersion() {
return version;
}
public byte[] getPrivateKey() {
return privateKey;
}
public byte[] getPublicKey() {
return publicKey;
}
}

View file

@ -0,0 +1,57 @@
package info.FrostFS.sdk;
import io.grpc.ChannelCredentials;
import org.apache.commons.lang3.StringUtils;
public class ClientSettings {
private static final String ERROR_TEMPLATE = "%s is required parameter.";
public String key;
public String host;
public ChannelCredentials creds;
public ClientSettings(String key, String host) {
this.key = key;
this.host = host;
}
public ChannelCredentials getCreds() {
return creds;
}
public void setCreds(ChannelCredentials creds) {
this.creds = creds;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void validate() {
StringBuilder errorMessage = new StringBuilder();
if (StringUtils.isEmpty(key)) {
errorMessage.append(String.format(ERROR_TEMPLATE, "Key")).append(System.lineSeparator());
}
if (StringUtils.isEmpty(host)) {
errorMessage.append(String.format(ERROR_TEMPLATE, "Host")).append(System.lineSeparator());
}
if (errorMessage.length() != 0) {
throw new IllegalArgumentException(errorMessage.toString());
}
}
}

View file

@ -1,89 +1,26 @@
package info.FrostFS.sdk;
import frostFS.container.ContainerServiceGrpc;
import frostFS.netmap.NetmapServiceGrpc;
import frostFS.object.ObjectServiceGrpc;
import frostFS.session.SessionServiceGrpc;
import io.grpc.Channel;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.ChannelCredentials;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLException;
import java.net.URI;
import java.net.URISyntaxException;
import static java.util.Objects.isNull;
public class GrpcClient {
private static final Logger log = LoggerFactory.getLogger(GrpcClient.class);
private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceBlockingClient;
private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceBlockingClient;
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient;
private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceBlockingClient;
public GrpcClient(String host) {
Channel channel = initGrpcChannel(host);
this.containerServiceBlockingClient = ContainerServiceGrpc.newBlockingStub(channel);
this.netmapServiceBlockingClient = NetmapServiceGrpc.newBlockingStub(channel);
this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(channel);
this.objectServiceClient = ObjectServiceGrpc.newStub(channel);
this.sessionServiceBlockingClient = SessionServiceGrpc.newBlockingStub(channel);
}
public static Channel initGrpcChannel(String host) {
URI uri;
public static Channel initGrpcChannel(String host, ChannelCredentials creds) {
try {
uri = new URI(host);
URI uri = new URI(host);
var channelBuilder = isNull(creds) ? NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort())
: NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort(), creds);
return channelBuilder.usePlaintext().build();
} catch (URISyntaxException exp) {
var message = String.format("Host %s has invalid format. Error: %s", host, exp.getMessage());
log.error(message);
throw new IllegalArgumentException(message);
}
var channelBuilder = NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort())
.usePlaintext();
switch (uri.getScheme()) {
case "https":
try {
channelBuilder.sslContext(
GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build()
);
} catch (SSLException e) {
throw new RuntimeException(e);
}
break;
case "http":
break;
default:
var message = String.format("Host %s has invalid URI scheme: %s", host, uri.getScheme());
log.error(message);
throw new IllegalArgumentException(message);
}
return channelBuilder.build();
}
public ContainerServiceGrpc.ContainerServiceBlockingStub getContainerServiceBlockingClient() {
return containerServiceBlockingClient;
}
public NetmapServiceGrpc.NetmapServiceBlockingStub getNetmapServiceBlockingClient() {
return netmapServiceBlockingClient;
}
public ObjectServiceGrpc.ObjectServiceBlockingStub getObjectServiceBlockingClient() {
return objectServiceBlockingClient;
}
public ObjectServiceGrpc.ObjectServiceStub getObjectServiceClient() {
return objectServiceClient;
}
public SessionServiceGrpc.SessionServiceBlockingStub getSessionServiceBlockingClient() {
return sessionServiceBlockingClient;
}
}

View file

@ -0,0 +1,54 @@
package info.FrostFS.sdk;
import info.FrostFS.sdk.enums.BasicAcl;
import info.FrostFS.sdk.enums.ObjectType;
import info.FrostFS.sdk.jdo.*;
import info.FrostFS.sdk.jdo.netmap.PlacementPolicy;
import info.FrostFS.sdk.jdo.netmap.Replica;
import info.FrostFS.sdk.services.FrostFSClient;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
public class Main {
public static void main(String[] args) throws Exception {
ClientSettings clientSettings = new ClientSettings("KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq", "http://localhost:8080");
FrostFSClient frostFSClient = new FrostFSClient(clientSettings);
/*
var res2 = frostFSClient.searchObjectsAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"));
*/
ObjectFrostFs res3 = frostFSClient
.getObjectAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"), new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww"));
var ttttt = frostFSClient.getNetworkSettingsAsync();
Container container2 = frostFSClient.getContainerAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"));
var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)});
var containerId = frostFSClient.createContainerAsync(new Container(BasicAcl.PUBLIC_RW, placementPolicy));
Thread.sleep(1000);
FileInputStream file = null;
try {
file = new FileInputStream("/home/ori/Desktop/cat.jpg");
var cat = new ObjectHeader(containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")});
frostFSClient.putObjectAsync(cat, file);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
var res = frostFSClient.searchObjectsAsync(containerId);
Container container = frostFSClient.getContainerAsync(containerId);
List<ContainerId> containerIds = frostFSClient.listContainersAsync();
/*
frostFSClient.deleteContainerAsync(containerId);
*/
containerIds = frostFSClient.listContainersAsync();
System.out.println();
}
}

View file

@ -62,21 +62,27 @@ public class RequestSigner {
return signature;
}
public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, byte[] privateKey, AbstractMessage message) {
public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey,
byte[] privateKey,
AbstractMessage message) {
return frostFS.refs.Types.SignatureRFC6979.newBuilder()
.setKey(ByteString.copyFrom(publicKey))
.setSign(ByteString.copyFrom(signRFC6979(privateKey, message.toByteArray())))
.build();
}
public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, byte[] privateKey, ByteString data) {
public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey,
byte[] privateKey,
ByteString data) {
return frostFS.refs.Types.SignatureRFC6979.newBuilder()
.setKey(ByteString.copyFrom(publicKey))
.setSign(ByteString.copyFrom(signRFC6979(privateKey, data.toByteArray())))
.build();
}
public static frostFS.refs.Types.Signature signMessagePart(byte[] publicKey, byte[] privateKey, AbstractMessage data) {
public static frostFS.refs.Types.Signature signMessagePart(byte[] publicKey,
byte[] privateKey,
AbstractMessage data) {
var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray();
return frostFS.refs.Types.Signature.newBuilder()
@ -101,13 +107,22 @@ public class RequestSigner {
var verifyOrigin = (AbstractMessage) verify.getField(verify.getDescriptorForType().findFieldByName("origin"));
if (verifyOrigin.getSerializedSize() == 0) {
verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("body_signature"), signMessagePart(publicKey, privateKey, body));
verifyBuilder.setField(
verifyBuilder.getDescriptorForType().findFieldByName("body_signature"),
signMessagePart(publicKey, privateKey, body)
);
} else {
verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin);
}
verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"), signMessagePart(publicKey, privateKey, meta));
verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"), signMessagePart(publicKey, privateKey, verifyOrigin));
verifyBuilder.setField(
verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"),
signMessagePart(publicKey, privateKey, meta)
);
verifyBuilder.setField(
verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"),
signMessagePart(publicKey, privateKey, verifyOrigin)
);
request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build());
}

View file

@ -22,10 +22,12 @@ import static org.bouncycastle.crypto.util.DigestFactory.createSHA256;
import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray;
public class Verifier {
public static final int RFC6979_SIGNATURE_SIZE = 64;
public static final int RFC6979_SIG_SIZE = 64;
public static boolean verifyRFC6979(Types.SignatureRFC6979 signature, AbstractMessage message) {
return verifyRFC6979(signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray());
return verifyRFC6979(
signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray()
);
}
public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) {
@ -45,17 +47,17 @@ public class Verifier {
}
private static BigInteger[] decodeSignature(byte[] sig) {
if (sig.length != RFC6979_SIGNATURE_SIZE) {
if (sig.length != RFC6979_SIG_SIZE) {
throw new IllegalArgumentException(
String.format("Wrong signature size. Expected length=%s, actual=%s",
RFC6979_SIGNATURE_SIZE, sig.length)
RFC6979_SIG_SIZE, sig.length)
);
}
var rs = new BigInteger[2];
rs[0] = fromUnsignedByteArray(Arrays.copyOfRange(sig, 0, (RFC6979_SIGNATURE_SIZE / 2) - 1));
rs[1] = fromUnsignedByteArray(Arrays.copyOfRange(sig, RFC6979_SIGNATURE_SIZE / 2, RFC6979_SIGNATURE_SIZE - 1));
rs[0] = fromUnsignedByteArray(Arrays.copyOfRange(sig, 0, (RFC6979_SIG_SIZE / 2) - 1));
rs[1] = fromUnsignedByteArray(Arrays.copyOfRange(sig, RFC6979_SIG_SIZE / 2, RFC6979_SIG_SIZE - 1));
return rs;
}

View file

@ -0,0 +1,19 @@
package info.FrostFS.sdk.services;
import info.FrostFS.sdk.tools.ClientEnvironment;
public class ContextAccessor {
protected ClientEnvironment context;
public ContextAccessor(ClientEnvironment context) {
this.context = context;
}
public ClientEnvironment getContext() {
return context;
}
public void setContext(ClientEnvironment context) {
this.context = context;
}
}

View file

@ -0,0 +1,134 @@
package info.FrostFS.sdk.services;
import frostFS.session.Types;
import info.FrostFS.sdk.ClientSettings;
import info.FrostFS.sdk.jdo.*;
import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot;
import info.FrostFS.sdk.jdo.netmap.NodeInfo;
import info.FrostFS.sdk.services.impl.ContainerService;
import info.FrostFS.sdk.services.impl.NetmapService;
import info.FrostFS.sdk.services.impl.ObjectService;
import info.FrostFS.sdk.services.impl.SessionService;
import info.FrostFS.sdk.tools.ClientEnvironment;
import info.FrostFS.sdk.tools.NetworkSettings;
import io.grpc.Channel;
import java.io.FileInputStream;
import java.util.List;
import static info.FrostFS.sdk.GrpcClient.initGrpcChannel;
import static java.util.Objects.isNull;
public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient {
private final ContainerService containerService;
private final NetmapService netmapService;
private final ObjectService objectService;
private final SessionService sessionService;
private final ClientEnvironment clientEnvironment;
public FrostFSClient(ClientSettings clientSettings) {
if (isNull(clientSettings)) {
throw new IllegalArgumentException("Options must be initialized");
}
clientSettings.validate();
Channel channel = initGrpcChannel(clientSettings.getHost(), clientSettings.getCreds());
this.clientEnvironment =
new ClientEnvironment(clientSettings.getKey(), channel, new Version(2, 13), this);
this.containerService = new ContainerService(clientEnvironment);
this.netmapService = new NetmapService(clientEnvironment);
this.sessionService = new SessionService(clientEnvironment);
this.objectService = new ObjectService(clientEnvironment);
checkFrostFsVersionSupport(clientEnvironment.getVersion());
}
private void checkFrostFsVersionSupport(Version version) {
var localNodeInfo = netmapService.getLocalNodeInfoAsync();
if (!localNodeInfo.getVersion().isSupported(version)) {
var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion());
System.out.println(msg);
throw new IllegalArgumentException(msg);
}
}
@Override
public Container getContainerAsync(ContainerId cid) {
return containerService.getContainerAsync(cid);
}
@Override
public List<ContainerId> listContainersAsync() {
return containerService.listContainersAsync();
}
@Override
public ContainerId createContainerAsync(Container container) {
return containerService.createContainerAsync(container);
}
@Override
public void deleteContainerAsync(ContainerId cid) {
containerService.deleteContainerAsync(cid);
}
@Override
public ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId) {
return objectService.getObjectHeadAsync(containerId, objectId);
}
@Override
public ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId) {
return objectService.getObjectAsync(containerId, objectId);
}
@Override
public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) {
return objectService.putObjectAsync(header, payload);
}
@Override
public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) {
return objectService.putObjectAsync(header, payload);
}
@Override
public void deleteObjectAsync(ContainerId containerId, ObjectId objectId) {
objectService.deleteObjectAsync(containerId, objectId);
}
@Override
public Iterable<ObjectId> searchObjectsAsync(ContainerId cid, ObjectFilter... filters) {
return objectService.searchObjectsAsync(cid, filters);
}
@Override
public NetmapSnapshot getNetmapSnapshotAsync() {
return netmapService.getNetmapSnapshotAsync();
}
@Override
public NodeInfo getLocalNodeInfoAsync() {
return netmapService.getLocalNodeInfoAsync();
}
@Override
public NetworkSettings getNetworkSettingsAsync() {
return netmapService.getNetworkSettingsAsync();
}
@Override
public SessionToken createSessionAsync(long expiration) {
return sessionService.createSessionAsync(expiration);
}
public Types.SessionToken createSessionInternalAsync(long expiration) {
return sessionService.createSessionInternalAsync(expiration);
}
@Override
public ObjectId CalculateObjectId(ObjectHeader header) {
return null;
}
}

View file

@ -0,0 +1,14 @@
package info.FrostFS.sdk.services;
import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot;
import info.FrostFS.sdk.jdo.netmap.NodeInfo;
import info.FrostFS.sdk.tools.NetworkSettings;
public interface NetmapClient {
NetmapSnapshot getNetmapSnapshotAsync();
NodeInfo getLocalNodeInfoAsync();
NetworkSettings getNetworkSettingsAsync();
}

View file

@ -0,0 +1,8 @@
package info.FrostFS.sdk.services;
import info.FrostFS.sdk.jdo.SessionToken;
public interface SessionClient {
SessionToken createSessionAsync(long expiration);
}

View file

@ -0,0 +1,8 @@
package info.FrostFS.sdk.services;
import info.FrostFS.sdk.jdo.ObjectHeader;
import info.FrostFS.sdk.jdo.ObjectId;
public interface ToolsClient {
ObjectId CalculateObjectId(ObjectHeader header);
}

View file

@ -2,7 +2,6 @@ package info.FrostFS.sdk.services.impl;
import frostFS.container.ContainerServiceGrpc;
import frostFS.container.Service;
import info.FrostFS.sdk.Client;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.jdo.Container;
import info.FrostFS.sdk.jdo.ContainerId;
@ -11,6 +10,8 @@ import info.FrostFS.sdk.mappers.ContainerMapper;
import info.FrostFS.sdk.mappers.OwnerIdMapper;
import info.FrostFS.sdk.mappers.VersionMapper;
import info.FrostFS.sdk.services.ContainerClient;
import info.FrostFS.sdk.services.ContextAccessor;
import info.FrostFS.sdk.tools.ClientEnvironment;
import java.util.List;
import java.util.stream.Collectors;
@ -19,23 +20,24 @@ import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestSigner.sign;
import static info.FrostFS.sdk.RequestSigner.signRFC6979;
public class ContainerService implements ContainerClient {
public class ContainerService extends ContextAccessor implements ContainerClient {
private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient;
private final Client client;
public ContainerService(ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient, Client client) {
this.containerServiceAsyncClient = containerServiceAsyncClient;
this.client = client;
public ContainerService(ClientEnvironment clientEnvironment) {
super(clientEnvironment);
this.containerServiceAsyncClient = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel());
}
public Container getContainerAsync(ContainerId cid) {
var request = Service.GetRequest.newBuilder()
.setBody(
Service.GetRequest.Body.newBuilder().setContainerId(ContainerIdMapper.toGrpcMessage(cid)).build()
Service.GetRequest.Body.newBuilder()
.setContainerId(ContainerIdMapper.toGrpcMessage(cid))
.build()
);
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = containerServiceAsyncClient.get(request.build());
@ -46,11 +48,13 @@ public class ContainerService implements ContainerClient {
public List<ContainerId> listContainersAsync() {
var request = Service.ListRequest.newBuilder()
.setBody(
Service.ListRequest.Body.newBuilder().setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())).build()
Service.ListRequest.Body.newBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId()))
.build()
);
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = containerServiceAsyncClient.list(request.build());
@ -65,20 +69,22 @@ public class ContainerService implements ContainerClient {
var grpcContainer = ContainerMapper.toGrpcMessage(container);
grpcContainer = grpcContainer.toBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(client.getVersion()))
.setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(context.getVersion()))
.build();
var request = Service.PutRequest.newBuilder()
.setBody(
Service.PutRequest.Body.newBuilder()
.setContainer(grpcContainer)
.setSignature(signRFC6979(client.getPublicKey(), client.getPrivateKey(), grpcContainer))
.setSignature(
signRFC6979(context.getPublicKey(), context.getPrivateKey(), grpcContainer)
)
.build()
);
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = containerServiceAsyncClient.put(request.build());
@ -93,12 +99,14 @@ public class ContainerService implements ContainerClient {
.setBody(
Service.DeleteRequest.Body.newBuilder()
.setContainerId(grpcContainerId)
.setSignature(signRFC6979(client.getPublicKey(), client.getPrivateKey(), grpcContainerId.getValue()))
.setSignature(signRFC6979(
context.getPublicKey(), context.getPrivateKey(), grpcContainerId.getValue()
))
.build()
);
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = containerServiceAsyncClient.delete(request.build());

View file

@ -1,85 +0,0 @@
package info.FrostFS.sdk.services.impl;
import info.FrostFS.sdk.Client;
import info.FrostFS.sdk.GrpcClient;
import info.FrostFS.sdk.jdo.*;
import info.FrostFS.sdk.services.ContainerClient;
import info.FrostFS.sdk.services.ObjectClient;
import java.io.FileInputStream;
import java.util.List;
public class FrostFSClient implements ContainerClient, ObjectClient {
private final ContainerService containerService;
private final NetmapService netmapService;
private final ObjectService objectService;
public FrostFSClient(GrpcClient grpcClient, Client client) {
this.containerService = new ContainerService(grpcClient.getContainerServiceBlockingClient(), client);
this.netmapService = new NetmapService(grpcClient.getNetmapServiceBlockingClient(), client);
SessionService sessionService = new SessionService(grpcClient.getSessionServiceBlockingClient(), client);
this.objectService = new ObjectService(
grpcClient.getObjectServiceBlockingClient(), grpcClient.getObjectServiceClient(), sessionService, client
);
checkFrostFsVersionSupport(client);
}
private void checkFrostFsVersionSupport(Client client) {
var localNodeInfo = netmapService.getLocalNodeInfoAsync();
if (!localNodeInfo.getVersion().isSupported(client.getVersion())) {
var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion());
System.out.println(msg);
throw new IllegalArgumentException(msg);
}
}
@Override
public Container getContainerAsync(ContainerId cid) {
return containerService.getContainerAsync(cid);
}
@Override
public List<ContainerId> listContainersAsync() {
return containerService.listContainersAsync();
}
@Override
public ContainerId createContainerAsync(Container container) {
return containerService.createContainerAsync(container);
}
@Override
public void deleteContainerAsync(ContainerId cid) {
containerService.deleteContainerAsync(cid);
}
@Override
public ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId) {
return objectService.getObjectHeadAsync(containerId, objectId);
}
@Override
public ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId) {
return objectService.getObjectAsync(containerId, objectId);
}
@Override
public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) {
return objectService.putObjectAsync(header, payload);
}
@Override
public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) {
return objectService.putObjectAsync(header, payload);
}
@Override
public void deleteObjectAsync(ContainerId containerId, ObjectId objectId) {
objectService.deleteObjectAsync(containerId, objectId);
}
@Override
public Iterable<ObjectId> searchObjectsAsync(ContainerId cid, ObjectFilter... filters) {
return objectService.searchObjectsAsync(cid, filters);
}
}

View file

@ -2,30 +2,124 @@ package info.FrostFS.sdk.services.impl;
import frostFS.netmap.NetmapServiceGrpc;
import frostFS.netmap.Service;
import info.FrostFS.sdk.Client;
import frostFS.netmap.Types;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot;
import info.FrostFS.sdk.jdo.netmap.NodeInfo;
import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper;
import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper;
import info.FrostFS.sdk.services.ContextAccessor;
import info.FrostFS.sdk.services.NetmapClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import info.FrostFS.sdk.tools.NetworkSettings;
import java.nio.charset.StandardCharsets;
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestSigner.sign;
import static java.util.Objects.nonNull;
public class NetmapService {
private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceAsyncClient;
private final Client client;
public class NetmapService extends ContextAccessor implements NetmapClient {
private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceClient;
public NetmapService(NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceAsyncClient, Client client) {
this.netmapServiceAsyncClient = netmapServiceAsyncClient;
this.client = client;
public NetmapService(ClientEnvironment clientEnvironment) {
super(clientEnvironment);
this.netmapServiceClient = NetmapServiceGrpc.newBlockingStub(context.getChannel());
}
private static boolean getBoolValue(byte[] bytes) {
for (var byteValue : bytes) {
if (byteValue != 0) return true;
}
return false;
}
private static long getLongValue(byte[] bytes) {
long val = 0;
for (var i = bytes.length - 1; i >= 0; i--) {
val = (val << 8) + bytes[i];
}
return val;
}
private static void setNetworksParam(Types.NetworkConfig.Parameter param, NetworkSettings settings) {
var key = new String(param.getKey().toByteArray(), StandardCharsets.UTF_8);
var valueBytes = param.getValue().toByteArray();
switch (key) {
case "AuditFee":
settings.setAuditFee(getLongValue(valueBytes));
break;
case "BasicIncomeRate":
settings.setBasicIncomeRate(getLongValue(valueBytes));
break;
case "ContainerFee":
settings.setContainerFee(getLongValue(valueBytes));
break;
case "ContainerAliasFee":
settings.setContainerAliasFee(getLongValue(valueBytes));
break;
case "EpochDuration":
settings.setEpochDuration(getLongValue(valueBytes));
break;
case "InnerRingCandidateFee":
settings.setiRCandidateFee(getLongValue(valueBytes));
break;
case "MaxECDataCount":
settings.setMaxECDataCount(getLongValue(valueBytes));
break;
case "MaxECParityCount":
settings.setMaxECParityCount(getLongValue(valueBytes));
break;
case "MaxObjectSize":
settings.setMaxObjectSize(getLongValue(valueBytes));
break;
case "WithdrawFee":
settings.setWithdrawalFee(getLongValue(valueBytes));
break;
case "HomomorphicHashingDisabled":
settings.setHomomorphicHashingDisabled(getBoolValue(valueBytes));
break;
case "MaintenanceModeAllowed":
settings.setMaintenanceModeAllowed(getBoolValue(valueBytes));
break;
default:
settings.getUnnamedSettings().put(key, valueBytes);
break;
}
}
@Override
public NetworkSettings getNetworkSettingsAsync() {
if (nonNull(context.getNetworkSettings())) {
return context.getNetworkSettings();
}
var info = getNetworkInfoAsync();
var settings = new NetworkSettings();
for (var param : info.getBody().getNetworkInfo().getNetworkConfig().getParametersList()) {
setNetworksParam(param, settings);
}
context.setNetworkSettings(settings);
return settings;
}
@Override
public NodeInfo getLocalNodeInfoAsync() {
var request = Service.LocalNodeInfoRequest.newBuilder()
.setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build());
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = netmapServiceAsyncClient.localNodeInfo(request.build());
var response = netmapServiceClient.localNodeInfo(request.build());
Verifier.checkResponse(response);
return NodeInfoMapper.toModel(response.getBody());
}
@ -34,9 +128,28 @@ public class NetmapService {
var request = Service.NetworkInfoRequest.newBuilder()
.setBody(Service.NetworkInfoRequest.Body.newBuilder().build());
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
return netmapServiceAsyncClient.networkInfo(request.build());
var response = netmapServiceClient.networkInfo(request.build());
Verifier.checkResponse(response);
return response;
}
@Override
public NetmapSnapshot getNetmapSnapshotAsync() {
var request = Service.NetmapSnapshotRequest.newBuilder()
.setBody(Service.NetmapSnapshotRequest.Body.newBuilder().build());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = netmapServiceClient.netmapSnapshot(request.build());
Verifier.checkResponse(response);
return NetmapSnapshotMapper.toModel(response);
}
}

View file

@ -5,11 +5,12 @@ import com.google.protobuf.ByteString;
import frostFS.object.ObjectServiceGrpc;
import frostFS.object.Service;
import frostFS.refs.Types;
import info.FrostFS.sdk.Client;
import info.FrostFS.sdk.Verifier;
import info.FrostFS.sdk.jdo.*;
import info.FrostFS.sdk.mappers.*;
import info.FrostFS.sdk.services.ContextAccessor;
import info.FrostFS.sdk.services.ObjectClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
@ -25,21 +26,14 @@ import static info.FrostFS.sdk.RequestConstructor.addObjectSessionToken;
import static info.FrostFS.sdk.RequestSigner.sign;
import static java.util.Objects.nonNull;
public class ObjectService implements ObjectClient {
public class ObjectService extends ContextAccessor implements ObjectClient {
private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient;
private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient;
private final SessionService sessionService;
private final Client client;
public ObjectService(ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceAsyncClient,
ObjectServiceGrpc.ObjectServiceStub objectServiceClient,
SessionService sessionService,
Client client) {
this.objectServiceBlockingClient = objectServiceAsyncClient;
this.objectServiceClient = objectServiceClient;
this.client = client;
this.sessionService = sessionService;
public ObjectService(ClientEnvironment clientEnvironment) {
super(clientEnvironment);
this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(context.getChannel());
this.objectServiceClient = ObjectServiceGrpc.newStub(context.getChannel());
}
@Override
@ -55,8 +49,8 @@ public class ObjectService implements ObjectClient {
).build()
);
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = objectServiceBlockingClient.head(request.build());
Verifier.checkResponse(response);
@ -66,7 +60,7 @@ public class ObjectService implements ObjectClient {
@Override
public ObjectFrostFs getObjectAsync(ContainerId cid, ObjectId oid) {
var sessionToken = sessionService.createSessionAsync(-1);
var sessionToken = context.getFrostFSClient().createSessionInternalAsync(-1);
var request = Service.GetRequest.newBuilder()
.setBody(
@ -81,12 +75,12 @@ public class ObjectService implements ObjectClient {
.build()
);
addMetaHeader(request, null);
addMetaHeader(request);
addObjectSessionToken(
request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid),
frostFS.session.Types.ObjectSessionContext.Verb.GET, client.getPublicKey(), client.getPrivateKey()
frostFS.session.Types.ObjectSessionContext.Verb.GET, context.getPublicKey(), context.getPrivateKey()
);
sign(request, client.getPublicKey(), client.getPrivateKey());
sign(request, context.getPublicKey(), context.getPrivateKey());
var obj = getObject(request.build());
@ -106,8 +100,8 @@ public class ObjectService implements ObjectClient {
)
.build());
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var response = objectServiceBlockingClient.delete(request.build());
Verifier.checkResponse(response);
@ -136,8 +130,8 @@ public class ObjectService implements ObjectClient {
var request = Service.SearchRequest.newBuilder()
.setBody(body.build());
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
var objectsIds = searchObjects(request.build());
@ -169,12 +163,12 @@ public class ObjectService implements ObjectClient {
}
private ObjectId putObject(ObjectHeader header, InputStream payload) {
var sessionToken = sessionService.createSessionAsync(-1);
var sessionToken = context.getFrostFSClient().createSessionInternalAsync(-1);
var hdr = ObjectHeaderMapper.toGrpcMessage(header);
hdr = hdr.toBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(client.getVersion()))
.setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId()))
.setVersion(VersionMapper.toGrpcMessage(context.getVersion()))
.build();
var oid = Types.ObjectID.newBuilder().setValue(getSha256(hdr)).build();
@ -187,12 +181,12 @@ public class ObjectService implements ObjectClient {
).build()
);
addMetaHeader(request, null);
addMetaHeader(request);
addObjectSessionToken(
request, sessionToken, hdr.getContainerId(), oid, frostFS.session.Types.ObjectSessionContext.Verb.PUT,
client.getPublicKey(), client.getPrivateKey()
context.getPublicKey(), context.getPrivateKey()
);
sign(request, client.getPublicKey(), client.getPrivateKey());
sign(request, context.getPublicKey(), context.getPrivateKey());
var writer = putObjectInit(request.build());
@ -208,7 +202,7 @@ public class ObjectService implements ObjectClient {
.build()
)
.clearVerifyHeader();
sign(request, client.getPublicKey(), client.getPrivateKey());
sign(request, context.getPublicKey(), context.getPrivateKey());
writer.write(request.build());
bufferLength = payload.readNBytes(buffer, 0, Constants.OBJECT_CHUNK_SIZE);
}

View file

@ -3,31 +3,41 @@ package info.FrostFS.sdk.services.impl;
import frostFS.session.Service;
import frostFS.session.SessionServiceGrpc;
import frostFS.session.Types;
import info.FrostFS.sdk.Client;
import info.FrostFS.sdk.jdo.SessionToken;
import info.FrostFS.sdk.mappers.OwnerIdMapper;
import info.FrostFS.sdk.mappers.SessionMapper;
import info.FrostFS.sdk.services.ContextAccessor;
import info.FrostFS.sdk.services.SessionClient;
import info.FrostFS.sdk.tools.ClientEnvironment;
import static info.FrostFS.sdk.RequestConstructor.addMetaHeader;
import static info.FrostFS.sdk.RequestSigner.sign;
public class SessionService {
public class SessionService extends ContextAccessor implements SessionClient {
private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient;
private final Client client;
public SessionService(SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient, Client client) {
this.sessionServiceAsyncClient = sessionServiceAsyncClient;
this.client = client;
public SessionService(ClientEnvironment clientEnvironment) {
super(clientEnvironment);
this.sessionServiceAsyncClient = SessionServiceGrpc.newBlockingStub(context.getChannel());
}
protected Types.SessionToken createSessionAsync(long expiration) {
@Override
public SessionToken createSessionAsync(long expiration) {
var sessionToken = createSessionInternalAsync(expiration);
var token = SessionMapper.serialize(sessionToken);
return new SessionToken(new byte[]{}, token);
}
public Types.SessionToken createSessionInternalAsync(long expiration) {
var request = Service.CreateRequest.newBuilder()
.setBody(
Service.CreateRequest.Body.newBuilder()
.setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId()))
.setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId()))
.setExpiration(expiration).build()
);
addMetaHeader(request, null);
sign(request, client.getPublicKey(), client.getPrivateKey());
addMetaHeader(request);
sign(request, context.getPublicKey(), context.getPrivateKey());
return createSession(request.build());
}

View file

@ -0,0 +1,60 @@
package info.FrostFS.sdk.tools;
import info.FrostFS.sdk.jdo.OwnerId;
import info.FrostFS.sdk.jdo.Version;
import info.FrostFS.sdk.services.FrostFSClient;
import io.grpc.Channel;
import static info.FrostFS.sdk.KeyExtension.getPrivateKeyFromWIF;
import static info.FrostFS.sdk.KeyExtension.loadPublicKey;
public class ClientEnvironment {
private final OwnerId ownerId;
private final Version version;
private final byte[] privateKey;
private final byte[] publicKey;
private final Channel channel;
private final FrostFSClient frostFSClient;
private NetworkSettings networkSettings;
public ClientEnvironment(String key, Channel channel, Version version, FrostFSClient frostFSClient) {
this.privateKey = getPrivateKeyFromWIF(key);
this.publicKey = loadPublicKey(privateKey);
this.ownerId = OwnerId.fromKey(publicKey);
this.version = version;
this.channel = channel;
this.frostFSClient = frostFSClient;
}
public Channel getChannel() {
return channel;
}
public NetworkSettings getNetworkSettings() {
return networkSettings;
}
public void setNetworkSettings(NetworkSettings networkSettings) {
this.networkSettings = networkSettings;
}
public FrostFSClient getFrostFSClient() {
return frostFSClient;
}
public OwnerId getOwnerId() {
return ownerId;
}
public Version getVersion() {
return version;
}
public byte[] getPrivateKey() {
return privateKey;
}
public byte[] getPublicKey() {
return publicKey;
}
}

View file

@ -0,0 +1,143 @@
package info.FrostFS.sdk.tools;
import java.util.HashMap;
import java.util.Map;
public class NetworkSettings {
public Long auditFee;
public Long basicIncomeRate;
public Long containerFee;
public Long containerAliasFee;
public Long innerRingCandidateFee;
public Long withdrawFee;
public Long epochDuration;
public Long iRCandidateFee;
public Long maxObjectSize;
public Long maxECDataCount;
public Long maxECParityCount;
public Long withdrawalFee;
public Boolean homomorphicHashingDisabled;
public Boolean maintenanceModeAllowed;
public Map<String, Object> unnamedSettings = new HashMap<>();
public Long getAuditFee() {
return auditFee;
}
public void setAuditFee(Long auditFee) {
this.auditFee = auditFee;
}
public Long getBasicIncomeRate() {
return basicIncomeRate;
}
public void setBasicIncomeRate(Long basicIncomeRate) {
this.basicIncomeRate = basicIncomeRate;
}
public long getContainerFee() {
return containerFee;
}
public void setContainerFee(long containerFee) {
this.containerFee = containerFee;
}
public long getContainerAliasFee() {
return containerAliasFee;
}
public void setContainerAliasFee(long containerAliasFee) {
this.containerAliasFee = containerAliasFee;
}
public long getInnerRingCandidateFee() {
return innerRingCandidateFee;
}
public void setInnerRingCandidateFee(long innerRingCandidateFee) {
this.innerRingCandidateFee = innerRingCandidateFee;
}
public long getWithdrawFee() {
return withdrawFee;
}
public void setWithdrawFee(long withdrawFee) {
this.withdrawFee = withdrawFee;
}
public long getEpochDuration() {
return epochDuration;
}
public void setEpochDuration(long epochDuration) {
this.epochDuration = epochDuration;
}
public long getiRCandidateFee() {
return iRCandidateFee;
}
public void setiRCandidateFee(long iRCandidateFee) {
this.iRCandidateFee = iRCandidateFee;
}
public long getMaxObjectSize() {
return maxObjectSize;
}
public void setMaxObjectSize(long maxObjectSize) {
this.maxObjectSize = maxObjectSize;
}
public long getMaxECDataCount() {
return maxECDataCount;
}
public void setMaxECDataCount(long maxECDataCount) {
this.maxECDataCount = maxECDataCount;
}
public long getMaxECParityCount() {
return maxECParityCount;
}
public void setMaxECParityCount(long maxECParityCount) {
this.maxECParityCount = maxECParityCount;
}
public long getWithdrawalFee() {
return withdrawalFee;
}
public void setWithdrawalFee(long withdrawalFee) {
this.withdrawalFee = withdrawalFee;
}
public boolean isHomomorphicHashingDisabled() {
return homomorphicHashingDisabled;
}
public void setHomomorphicHashingDisabled(boolean homomorphicHashingDisabled) {
this.homomorphicHashingDisabled = homomorphicHashingDisabled;
}
public boolean isMaintenanceModeAllowed() {
return maintenanceModeAllowed;
}
public void setMaintenanceModeAllowed(boolean maintenanceModeAllowed) {
this.maintenanceModeAllowed = maintenanceModeAllowed;
}
public Map<String, Object> getUnnamedSettings() {
return unnamedSettings;
}
public void setUnnamedSettings(Map<String, Object> unnamedSettings) {
this.unnamedSettings = unnamedSettings;
}
}

View file

@ -0,0 +1,19 @@
package info.FrostFS.sdk.jdo;
public class SessionToken {
public byte[] id;
public byte[] sessionKey;
public SessionToken(byte[] id, byte[] sessionKey) {
this.id = id;
this.sessionKey = sessionKey;
}
public byte[] getId() {
return id;
}
public byte[] getSessionKey() {
return sessionKey;
}
}

View file

@ -0,0 +1,21 @@
package info.FrostFS.sdk.jdo.netmap;
import java.util.List;
public class NetmapSnapshot {
public Long epoch;
public List<NodeInfo> nodeInfoCollection;
public NetmapSnapshot(Long epoch, List<NodeInfo> nodeInfoCollection) {
this.epoch = epoch;
this.nodeInfoCollection = nodeInfoCollection;
}
public Long getEpoch() {
return epoch;
}
public List<NodeInfo> getNodeInfoCollection() {
return nodeInfoCollection;
}
}

View file

@ -1,11 +1,26 @@
package info.FrostFS.sdk.jdo.netmap;
import info.FrostFS.sdk.jdo.Version;
import info.FrostFS.sdk.enums.NodeState;
import info.FrostFS.sdk.jdo.Version;
import java.util.List;
import java.util.Map;
public class NodeInfo {
public NodeState state;
public Version version;
public List<String> addresses;
public Map<String, String> attributes;
public byte[] publicKey;
public NodeInfo(NodeState state, Version version, List<String> addresses,
Map<String, String> attributes, byte[] publicKey) {
this.state = state;
this.version = version;
this.addresses = addresses;
this.attributes = attributes;
this.publicKey = publicKey;
}
public NodeState getState() {
return state;
@ -23,8 +38,15 @@ public class NodeInfo {
this.version = version;
}
public NodeInfo(NodeState state, Version version) {
this.state = state;
this.version = version;
public byte[] getPublicKey() {
return publicKey;
}
public Map<String, String> getAttributes() {
return attributes;
}
public List<String> getAddresses() {
return addresses;
}
}

View file

@ -0,0 +1,31 @@
package info.FrostFS.sdk.mappers;
import com.google.protobuf.CodedOutputStream;
import com.google.protobuf.InvalidProtocolBufferException;
import frostFS.session.Types;
import java.io.IOException;
public class SessionMapper {
public static byte[] serialize(Types.SessionToken token)
{
try {
byte[] bytes = new byte[token.getSerializedSize()];
CodedOutputStream stream = CodedOutputStream.newInstance(bytes);
token.writeTo(stream);
return bytes;
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
public static Types.SessionToken deserializeSessionToken(byte[] bytes)
{
try {
return Types.SessionToken.newBuilder().mergeFrom(bytes).build();
} catch (InvalidProtocolBufferException exp) {
throw new IllegalArgumentException();
}
}
}

View file

@ -0,0 +1,18 @@
package info.FrostFS.sdk.mappers.netmap;
import frostFS.netmap.Service;
import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot;
import java.util.stream.Collectors;
public class NetmapSnapshotMapper {
public static NetmapSnapshot toModel(Service.NetmapSnapshotResponse netmap) {
return new NetmapSnapshot(
netmap.getBody().getNetmap().getEpoch(),
netmap.getBody().getNetmap().getNodesList().stream()
.map(t -> NodeInfoMapper.toModel(t, netmap.getMetaHeader().getVersion()))
.collect(Collectors.toList())
);
}
}

View file

@ -1,21 +1,36 @@
package info.FrostFS.sdk.mappers.netmap;
import frostFS.netmap.Service;
import frostFS.netmap.Types.NodeInfo.Attribute;
import frostFS.refs.Types;
import info.FrostFS.sdk.enums.NodeState;
import info.FrostFS.sdk.jdo.netmap.NodeInfo;
import info.FrostFS.sdk.mappers.VersionMapper;
import java.util.stream.Collectors;
import static java.util.Objects.isNull;
public class NodeInfoMapper {
public static NodeInfo toModel(Service.LocalNodeInfoResponse.Body nodeInfo) {
var nodeState = NodeState.get(nodeInfo.getNodeInfo().getState().getNumber());
return toModel(nodeInfo.getNodeInfo(), nodeInfo.getVersion());
}
public static NodeInfo toModel(frostFS.netmap.Types.NodeInfo nodeInfo, Types.Version version) {
NodeState nodeState = NodeState.get(nodeInfo.getState().getNumber());
if (isNull(nodeState)) {
throw new IllegalArgumentException(
String.format("Unknown NodeState. Value: %s.", nodeInfo.getNodeInfo().getState())
String.format("Unknown NodeState. Value: %s.", nodeInfo.getState())
);
}
return new NodeInfo(nodeState, VersionMapper.toModel(nodeInfo.getVersion()));
return new NodeInfo(
nodeState,
VersionMapper.toModel(version),
nodeInfo.getAddressesList(),
nodeInfo.getAttributesList().stream().collect(Collectors.toMap(Attribute::getKey, Attribute::getValue)),
nodeInfo.getPublicKey().toByteArray()
);
}
}