All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bdware.doip.event.PersistencePublisher Maven / Gradle / Ivy

There is a newer version: 1.5.4
Show 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.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 AuditDoipClient getOrCreateConnection(String subscriberId) {
        if (subscriberId.startsWith("tcp://")) {
            return getOrCreateConnectionSelf(subscriberId);
        }
        return client.convertDoidToRepo(subscriberId);
    }

    private AuditDoipClient getOrCreateConnectionSelf(String uri) {
        AuditDoipClient 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(() -> {
                AuditDoipClient 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.sendMessage(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();
                AuditDoipClient client = getOrCreateConnection(id);
                DoipMessage tosend = request.withNewDOID(request, je.getAsString());
                try {
                    if (!sent.contains(id)) {
                        sent.add(id);
                        client.sendMessage(tosend, null);
                    }
                } catch (Exception e) {
                    try {
                        client.reconnect();
                    } catch (DoipConnectException ex) {
                        throw new RuntimeException(ex);
                    }
                }
            });
        }).start();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy