2018-03-06 16:59:09 +03:00
|
|
|
/*
|
2015-12-18 16:20:47 +03:00
|
|
|
* Copyright 2015 Alexander Nozik.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
package inr.numass.client;
|
|
|
|
|
2016-10-12 10:55:09 +03:00
|
|
|
import hep.dataforge.io.envelopes.DefaultEnvelopeReader;
|
2017-07-31 20:19:55 +03:00
|
|
|
import hep.dataforge.io.envelopes.DefaultEnvelopeType;
|
2016-10-12 10:55:09 +03:00
|
|
|
import hep.dataforge.io.envelopes.Envelope;
|
|
|
|
import hep.dataforge.io.envelopes.EnvelopeBuilder;
|
|
|
|
import hep.dataforge.io.messages.Responder;
|
2015-12-18 16:20:47 +03:00
|
|
|
import hep.dataforge.meta.Meta;
|
|
|
|
import hep.dataforge.meta.MetaBuilder;
|
|
|
|
import hep.dataforge.values.Value;
|
2017-06-30 22:09:18 +03:00
|
|
|
import hep.dataforge.values.Values;
|
2017-07-08 22:04:29 +03:00
|
|
|
import inr.numass.data.storage.NumassStorage;
|
2018-03-06 16:59:09 +03:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
2016-10-09 14:04:26 +03:00
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import org.zeroturnaround.zip.ZipUtil;
|
|
|
|
|
|
|
|
import java.io.*;
|
2015-12-18 16:20:47 +03:00
|
|
|
import java.net.Socket;
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
import java.nio.channels.FileChannel;
|
|
|
|
import java.nio.file.StandardOpenOption;
|
2016-04-16 22:41:21 +03:00
|
|
|
import java.time.Instant;
|
2015-12-18 16:20:47 +03:00
|
|
|
import java.util.Arrays;
|
2016-10-09 20:13:25 +03:00
|
|
|
import java.util.Collection;
|
2015-12-18 16:20:47 +03:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
2018-03-06 16:59:09 +03:00
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
|
|
|
|
import static hep.dataforge.io.messages.MessagesKt.*;
|
2015-12-18 16:20:47 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author darksnake
|
|
|
|
*/
|
2016-10-09 20:13:25 +03:00
|
|
|
public class NumassClient implements AutoCloseable, Responder {
|
2015-12-18 16:20:47 +03:00
|
|
|
|
|
|
|
Socket socket;
|
|
|
|
|
|
|
|
public NumassClient(String address, int port) throws IOException {
|
|
|
|
socket = new Socket(address, port);
|
2016-04-13 18:13:59 +03:00
|
|
|
socket.setSoTimeout(300);
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 20:13:25 +03:00
|
|
|
|
|
|
|
public NumassClient(Meta meta) throws IOException {
|
|
|
|
this(meta.getString("ip", "192.168.111.1"), meta.getInt("port", 8335));
|
|
|
|
}
|
|
|
|
|
2015-12-18 16:20:47 +03:00
|
|
|
@Override
|
|
|
|
public void close() throws IOException {
|
|
|
|
if (!socket.isClosed()) {
|
2018-03-06 16:59:09 +03:00
|
|
|
write(getTerminator(), socket.getOutputStream());
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
socket.close();
|
|
|
|
}
|
|
|
|
|
2016-10-09 14:04:26 +03:00
|
|
|
@Override
|
|
|
|
public Envelope respond(Envelope message) {
|
2015-12-18 16:20:47 +03:00
|
|
|
try {
|
|
|
|
write(message, socket.getOutputStream());
|
|
|
|
return read(socket.getInputStream());
|
|
|
|
} catch (IOException ex) {
|
|
|
|
LoggerFactory.getLogger(getClass()).error("Error in envelope exchange", ex);
|
2018-03-06 16:59:09 +03:00
|
|
|
return errorResponseBase(message, ex).build();
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private Envelope read(InputStream is) throws IOException {
|
|
|
|
return new DefaultEnvelopeReader().readWithData(is);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void write(Envelope envelope, OutputStream os) throws IOException {
|
2018-02-25 20:06:11 +03:00
|
|
|
DefaultEnvelopeType.Companion.getINSTANCE().getWriter().write(os, envelope);
|
2015-12-18 16:20:47 +03:00
|
|
|
os.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
private EnvelopeBuilder requestActionBase(String type, String action) {
|
2018-03-06 16:59:09 +03:00
|
|
|
return requestBase(type).setMetaValue("action", action);
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public Meta getCurrentRun() {
|
2017-11-21 19:11:12 +03:00
|
|
|
return respond(requestActionBase("numass.run", "get").build()).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public Meta startRun(String name) {
|
2016-10-09 14:04:26 +03:00
|
|
|
return respond(requestActionBase("numass.run", "start")
|
2018-03-05 10:41:45 +03:00
|
|
|
.setMetaValue("path", name)
|
2017-11-21 19:11:12 +03:00
|
|
|
.build()).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public Meta resetRun() {
|
2016-10-09 14:04:26 +03:00
|
|
|
return respond(requestActionBase("numass.run", "reset")
|
2017-11-21 19:11:12 +03:00
|
|
|
.build()).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public Meta sendNumassData(String path, String fileName) {
|
|
|
|
try {
|
|
|
|
File file = new File(fileName);
|
|
|
|
ByteBuffer buffer;
|
|
|
|
String zipName = null;
|
|
|
|
if (file.isDirectory()) {
|
2018-03-28 16:59:40 +03:00
|
|
|
File tmpFile = File.createTempFile(file.getName(), NumassStorage.NUMASS_ZIP_EXTENSION);
|
2015-12-18 16:20:47 +03:00
|
|
|
tmpFile.deleteOnExit();
|
|
|
|
ZipUtil.pack(file, tmpFile);
|
|
|
|
zipName = file.getName();
|
|
|
|
file = tmpFile;
|
|
|
|
}
|
|
|
|
|
2018-03-28 16:59:40 +03:00
|
|
|
if (file.toString().endsWith(NumassStorage.NUMASS_ZIP_EXTENSION)) {
|
2015-12-18 16:20:47 +03:00
|
|
|
FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
|
|
|
|
buffer = ByteBuffer.allocate((int) channel.size());
|
|
|
|
channel.read(buffer);
|
|
|
|
if (zipName == null) {
|
2018-03-28 16:59:40 +03:00
|
|
|
zipName = file.getName().replace(NumassStorage.NUMASS_ZIP_EXTENSION, "");
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
} else {
|
2018-03-06 16:59:09 +03:00
|
|
|
return getErrorMeta(new FileNotFoundException(fileName));
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
2018-03-06 16:59:09 +03:00
|
|
|
Envelope bin = requestBase("numass.data")
|
|
|
|
.setMetaValue("action", "push")
|
|
|
|
.setMetaValue("path", path)
|
|
|
|
.setMetaValue("name", zipName)
|
2015-12-18 16:20:47 +03:00
|
|
|
.setData(buffer)
|
|
|
|
.build();
|
|
|
|
|
2017-11-21 19:11:12 +03:00
|
|
|
return respond(bin).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
} catch (IOException ex) {
|
2018-03-06 16:59:09 +03:00
|
|
|
return getErrorMeta(ex);
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get state map for given state names from the root state loader. If
|
|
|
|
* stateNames is empty, return all states.
|
|
|
|
*
|
2016-10-09 14:04:26 +03:00
|
|
|
* @param stateNames
|
2015-12-18 16:20:47 +03:00
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public Map<String, Value> getStates(String... stateNames) {
|
|
|
|
EnvelopeBuilder env = requestActionBase("numass.state", "get");
|
|
|
|
|
|
|
|
if (stateNames.length > 0) {
|
2018-03-05 10:41:45 +03:00
|
|
|
env.setMetaValue("name", Arrays.asList(stateNames));
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
2017-11-21 19:11:12 +03:00
|
|
|
Meta response = respond(env.build()).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
if (response.getBoolean("success", true)) {
|
|
|
|
Map<String, Value> res = new HashMap<>();
|
2018-03-06 16:59:09 +03:00
|
|
|
response.getMetaList("state").forEach((stateMeta) -> {
|
2015-12-18 16:20:47 +03:00
|
|
|
res.put(stateMeta.getString("name"), stateMeta.getValue("value"));
|
|
|
|
});
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a single state and return resulting envelope meta
|
|
|
|
*
|
|
|
|
* @param name
|
|
|
|
* @param value
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public Meta setState(String name, Object value) {
|
|
|
|
EnvelopeBuilder env = requestActionBase("numass.state", "set");
|
|
|
|
env.putMetaNode(new MetaBuilder("state")
|
|
|
|
.setValue("name", name)
|
|
|
|
.setValue("value", value)
|
|
|
|
.build());
|
|
|
|
|
2017-11-21 19:11:12 +03:00
|
|
|
return respond(env.build()).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set states and return resulting meta
|
|
|
|
*
|
|
|
|
* @param stateMap
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public Meta setState(Map<String, Value> stateMap) {
|
|
|
|
EnvelopeBuilder env = requestActionBase("numass.state", "set");
|
2018-03-06 16:59:09 +03:00
|
|
|
stateMap.entrySet().forEach((state) -> {
|
2015-12-18 16:20:47 +03:00
|
|
|
env.putMetaNode(new MetaBuilder("state")
|
|
|
|
.setValue("name", state.getKey())
|
|
|
|
.setValue("value", state.getValue())
|
|
|
|
.build());
|
2016-04-12 22:38:43 +03:00
|
|
|
});
|
2017-11-21 19:11:12 +03:00
|
|
|
return respond(env.build()).getMeta();
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|
|
|
|
|
2016-04-16 22:41:21 +03:00
|
|
|
public Meta addNote(String text, Instant time) {
|
|
|
|
EnvelopeBuilder env = requestActionBase("numass.notes", "push");
|
2018-03-05 10:41:45 +03:00
|
|
|
env.setMetaValue("note.text", text);
|
2016-04-16 22:41:21 +03:00
|
|
|
if (time != null) {
|
2018-03-05 10:41:45 +03:00
|
|
|
env.setMetaValue("note.time", time);
|
2016-04-16 22:41:21 +03:00
|
|
|
}
|
2017-11-21 19:11:12 +03:00
|
|
|
return respond(env.build()).getMeta();
|
2016-04-16 22:41:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public Meta getNotes(int limit) {
|
|
|
|
EnvelopeBuilder env = requestActionBase("numass.notes", "pull");
|
|
|
|
if (limit > 0) {
|
2018-03-05 10:41:45 +03:00
|
|
|
env.setMetaValue("limit", limit);
|
2016-04-16 22:41:21 +03:00
|
|
|
}
|
2017-11-21 19:11:12 +03:00
|
|
|
return respond(env.build()).getMeta();
|
2016-04-16 22:41:21 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 20:13:25 +03:00
|
|
|
/**
|
|
|
|
* Create remote storage with given meta
|
|
|
|
*
|
|
|
|
* @param path full path relative to root storage
|
|
|
|
* @param meta
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public Envelope createStorage(String path, Meta meta) {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create remote loader
|
|
|
|
*
|
|
|
|
* @param shelf full path to the shelf
|
|
|
|
* @param name the name of the loader
|
|
|
|
* @param meta loader meta
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public Envelope createLoader(String shelf, String name, Meta meta) {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send points to existing point loader
|
|
|
|
*
|
|
|
|
* @param shelf
|
|
|
|
* @param loaderName
|
|
|
|
* @param points
|
|
|
|
* @return
|
|
|
|
*/
|
2017-06-30 22:09:18 +03:00
|
|
|
public Envelope sendDataPoints(String shelf, String loaderName, Collection<Values> points) {
|
2016-10-09 20:13:25 +03:00
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
2018-03-06 16:59:09 +03:00
|
|
|
@NotNull
|
|
|
|
@Override
|
|
|
|
public CompletableFuture<Envelope> respondInFuture(@NotNull Envelope message) {
|
|
|
|
return CompletableFuture.supplyAsync(() -> respond(message));
|
|
|
|
}
|
2015-12-18 16:20:47 +03:00
|
|
|
}
|