org.bdware.doip.event.PersistencePublisher 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.AuditDoaClient;
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 org.rocksdb.RocksIterator;
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.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class PersistencePublisher implements Publisher {
private static final Gson GSON = new Gson();
// key 是topicId, value是[subscriber1,subscriber2,...]
// support only one topicId!
// key =
KVStore storageManager;
AuditDoaClient client;
AtomicInteger count;
static final String prefixOfEvent = "pfe_";
private AtomicBoolean initialized;
static Logger LOGGER = LogManager.getLogger(PersistencePublisher.class);
Map cachedClient;
public PersistencePublisher(KVStore storageManager, AuditDoaClient client) {
this.storageManager = storageManager;
this.client = client;
new Thread(() -> {
initializeCount();
}).start();
}
private void initializeCount() {
count = new AtomicInteger(0);
cachedClient = new ConcurrentHashMap<>();
initialized = new AtomicBoolean(false);
RocksIterator iter = storageManager.newIterator();
iter.seekToFirst();
for (; iter.isValid(); ) {
String key = new String(iter.key());
if (key.startsWith(prefixOfEvent)) {
count.incrementAndGet();
LOGGER.info("Value:" + new String(iter.value()));
}
iter.next();
}
initialized.set(true);
}
synchronized private void addSubscribers(String topicId, String subscriberId) {
JsonArray subscribers = getAsJson(topicId, new JsonArray()).getAsJsonArray();
JsonPrimitive sid = new JsonPrimitive(subscriberId);
if (!subscribers.contains(sid)) {
subscribers.add(sid);
storageManager.put(topicId, subscribers.toString());
}
}
synchronized private void removeSubscribers(String topicId, String subscriberId) {
JsonArray subscribers = getAsJson(topicId, new JsonArray()).getAsJsonArray();
JsonPrimitive sid = new JsonPrimitive(subscriberId);
if (subscribers.contains(sid)) {
subscribers.remove(sid);
storageManager.put(topicId, subscribers.toString());
}
}
private JsonElement getAsJson(String key, JsonElement defaultValue) {
String content = storageManager.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 getTcpDriectClient(subscriberId);
}
return client;
}
private DoipClient getTcpDriectClient(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;
}
AuditConfig config = AuditConfig.newInstance(new AuditRepo(null, null), AuditType.None, null);
client1 = new AuditDoipClient(config, 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);
int total = count.get();
if (needReplay) {
new Thread(() -> {
DoipClient client = getOrCreateConnection(subscriberId);
try {
for (int i = 0; i < total; i++) {
String msg = storageManager.get(prefixOfEvent + i);
DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
client.sendRawMessage(message, null);
}
} catch (Exception ignored) {
}
}).start();
}
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) {
throw new IllegalStateException("unsupported message type");
}
@Override
public DoipMessage sendDataInList(String topicId, String subscriberId, JsonArray indexList, DoipMessage request) {
throw new IllegalStateException("unsupported message type");
}
@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) {
if (!initialized.get()) Thread.yield();
JsonArray subscribers = getAsJson(topicId, new JsonArray()).getAsJsonArray();
request.header.parameters.attributes.addProperty("topicId", topicId);
request.header.parameters.attributes.addProperty("publishType", PublishMessageType.Data.name());
String key = prefixOfEvent + count.getAndIncrement();
storageManager.put(key, GSON.toJson(request));
new Thread(() -> {
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);
}
}
});
}).start();
}
}