org.bdware.doip.event.MultiTopicPersistencePublisher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of doip-audit-tool Show documentation
Show all versions of doip-audit-tool Show documentation
doip audit tool developed by bdware
The newest version!
package org.bdware.doip.event;
import com.google.gson.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.audit.client.AuditDoipClient;
import org.bdware.doip.audit.writer.AuditConfig;
import org.bdware.doip.audit.writer.AuditRepo;
import org.bdware.doip.audit.writer.AuditType;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.codec.doipMessage.DoipMessageFactory;
import org.bdware.doip.codec.doipMessage.DoipResponseCode;
import org.bdware.doip.codec.exception.DoipConnectException;
import org.bdware.doip.endpoint.client.ClientConfig;
import org.bdware.doip.endpoint.client.DoipClient;
import org.bdware.doip.endpoint.event.PublishMessageType;
import org.bdware.doip.endpoint.event.Publisher;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultiTopicPersistencePublisher implements Publisher {
private static final Gson GSON = new Gson();
// key 是topicId, value是[subscriber1,subscriber2,...]
// support only one topicId!
// key =
KVStore topicToSubscribers;
MultiTagColumnStorage topicToMessages;
DoipClient client;
static Logger LOGGER = LogManager.getLogger(MultiTopicPersistencePublisher.class);
Map cachedClient;
ExecutorService threadPool = Executors.newFixedThreadPool(20);
public MultiTopicPersistencePublisher(KVStore topicToSubscriber, MultiTagColumnStorage messageStorage, DoipClient client) {
this.topicToSubscribers = topicToSubscriber;
this.topicToMessages = messageStorage;
this.client = client;
cachedClient = new ConcurrentHashMap<>();
}
synchronized private void addSubscribers(String topicId, String subscriberId) {
JsonArray subscribers = getSubscribersAsJson(topicId, new JsonArray()).getAsJsonArray();
JsonPrimitive sid = new JsonPrimitive(subscriberId);
if (!subscribers.contains(sid)) {
subscribers.add(sid);
topicToSubscribers.put(topicId, subscribers.toString());
}
}
synchronized private void removeSubscribers(String topicId, String subscriberId) {
JsonArray subscribers = getSubscribersAsJson(topicId, new JsonArray()).getAsJsonArray();
JsonPrimitive sid = new JsonPrimitive(subscriberId);
if (subscribers.contains(sid)) {
subscribers.remove(sid);
topicToSubscribers.put(topicId, subscribers.toString());
}
}
private JsonElement getSubscribersAsJson(String key, JsonElement defaultValue) {
String content = topicToSubscribers.get(key);
try {
if (null != content && !content.isEmpty()) {
return JsonParser.parseString(content);
}
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
private DoipClient getOrCreateConnection(String subscriberId) {
if (subscriberId.startsWith("tcp://")) {
return getTcpDirectlyClient(subscriberId);
}
return client;
}
private DoipClient getTcpDirectlyClient(String uri) {
DoipClient client1 = cachedClient.get(uri);
if (client1 != null) {
if (!client1.isConnected()) {
try {
client1.reconnect();
} catch (DoipConnectException e) {
throw new RuntimeException(e);
}
}
return client1;
}
client1 = new AuditDoipClient(AuditConfig.newInstance(new AuditRepo(null, null), AuditType.None, null), null);
client1.connect(ClientConfig.fromUrl(uri));
cachedClient.put(uri, client1);
return client1;
}
@Override
public DoipMessage subscribe(String topicId, String subscriberId, boolean needReplay, DoipMessage request) {
addSubscribers(topicId, subscriberId);
long total = topicToMessages.size(topicId);
if (needReplay) {
threadPool.execute(() -> {
DoipClient client = getOrCreateConnection(subscriberId);
try {
for (int i = 0; i < total; i++) {
String msg = topicToMessages.get(topicId, i);
DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
client.sendRawMessage(message, null);
}
} catch (Exception ignored) {
}
});
}
DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
builder.createResponse(DoipResponseCode.Success, request).setBody((total + "").getBytes());
return builder.create();
}
@Override
public DoipMessage unsubscribe(String topicId, String subscriberId, DoipMessage request) {
removeSubscribers(topicId, subscriberId);
DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
builder.createResponse(DoipResponseCode.Success, request).setBody("success".getBytes(StandardCharsets.UTF_8));
return builder.create();
}
@Override
public DoipMessage sendDataInRange(String topicId, String subscriberId, long offset, long count, DoipMessage request) {
//TODO检查一下是不是在我列表里?
threadPool.execute(() -> {
DoipClient client = getOrCreateConnection(subscriberId);
try {
for (long i = offset; i < offset + count; i++) {
String msg = topicToMessages.get(topicId, i);
DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
message.header.parameters.id = subscriberId;
client.sendRawMessage(message, null);
}
} catch (Exception ignored) {
}
});
DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
builder.createResponse(DoipResponseCode.Success, request).setBody("success".getBytes(StandardCharsets.UTF_8));
return builder.create();
}
@Override
public DoipMessage sendDataInList(String topicId, String subscriberId, JsonArray indexList, DoipMessage request) {
//TODO检查一下是不是在我列表里?
threadPool.execute(() -> {
DoipClient client = getOrCreateConnection(subscriberId);
try {
for (JsonElement je : indexList) {
long i = je.getAsLong();
String msg = topicToMessages.get(topicId, i);
DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
message.header.parameters.id = subscriberId;
client.sendRawMessage(message, null);
}
} catch (Exception ignored) {
}
});
DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
builder.createResponse(DoipResponseCode.Success, request).setBody("success".getBytes(StandardCharsets.UTF_8));
return builder.create();
}
@Override
public DoipMessage verifyMerkelInRange(String topicId, String subscriberId, DoipMessage request) {
throw new IllegalStateException("unsupported message type");
}
@Override
public DoipMessage sendMerkelInRange(String topicId, String subscriberId, DoipMessage request) {
throw new IllegalStateException("unsupported message type");
}
@Override
public void publish(String topicId, DoipMessage request) {
JsonArray subscribers = getSubscribersAsJson(topicId, new JsonArray()).getAsJsonArray();
request.header.parameters.attributes.addProperty("topicId", topicId);
request.header.parameters.attributes.addProperty("publishType", PublishMessageType.Data.name());
topicToMessages.put(topicId, GSON.toJson(request));
threadPool.execute(() -> {
Set sent = new HashSet<>();
subscribers.forEach(je -> {
String id = je.getAsString();
DoipClient client = getOrCreateConnection(id);
DoipMessage tosend = request.withNewDOID(request, je.getAsString());
try {
if (!sent.contains(id)) {
sent.add(id);
client.sendRawMessage(tosend, null);
}
} catch (Exception e) {
try {
client.reconnect();
} catch (DoipConnectException ex) {
throw new RuntimeException(ex);
}
}
});
});
}
}