Search in sources :

Example 6 with FastBuildTree

use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.

the class TcpTransporter method processGossipRequest.

// --- GOSSIP REQUEST MESSAGE RECEIVED ---
protected Tree processGossipRequest(Tree data) throws Exception {
    // Debug
    String sender = data.get("sender", (String) null);
    if (debug) {
        logger.info("Gossip request received from \"" + sender + "\" node:\r\n" + data);
    }
    // Add "online" and "offline" response blocks
    LinkedList<NodeDescriptor> allNodes = new LinkedList<>(nodes.values());
    NodeDescriptor descriptor = getDescriptor();
    allNodes.add(descriptor);
    int size = allNodes.size() + 1;
    FastBuildTree onlineRsp = new FastBuildTree(size);
    FastBuildTree offlineRsp = new FastBuildTree(size);
    // Online / offline nodes in request
    Tree onlineReq = data.get("online");
    Tree offlineReq = data.get("offline");
    // Loop in nodes
    LinkedList<NodeDescriptor> disconnectedNodes = new LinkedList<>();
    for (NodeDescriptor node : allNodes) {
        node.writeLock.lock();
        try {
            Tree online = onlineReq == null ? null : onlineReq.get(node.nodeID);
            Tree offline = offlineReq == null ? null : offlineReq.get(node.nodeID);
            // Online or offline sequence number
            long seq = 0;
            // CPU data
            long cpuSeq = 0;
            int cpu = 0;
            if (offline != null) {
                if (!offline.isPrimitive()) {
                    logger.warn("Invalid \"offline\" block: " + offline.toString(false));
                    continue;
                }
                seq = offline.asLong();
            } else if (online != null) {
                if (!online.isEnumeration() || online.size() != 3) {
                    logger.warn("Invalid \"online\" block: " + online.toString(false));
                    continue;
                }
                seq = online.get(0).asLong();
                cpuSeq = online.get(1).asLong();
                cpu = online.get(2).asInteger();
            }
            if ((seq == 0 || seq < node.seq) && node.seq > 0) {
                // We have newer info or requester doesn't know it
                if (node.offlineSince == 0) {
                    if (!node.info.isEmpty()) {
                        if ((cpuSeq == 0 || cpuSeq < node.cpuSeq) && node.cpuSeq > 0) {
                            ArrayList<Object> array = new ArrayList<>(3);
                            array.add(node.info.asObject());
                            array.add(node.cpuSeq);
                            array.add(node.cpu);
                            onlineRsp.putUnsafe(node.nodeID, array);
                        } else {
                            onlineRsp.putUnsafe(node.nodeID, Collections.singletonList(node.info.asObject()));
                        }
                    }
                } else {
                    offlineRsp.putUnsafe(node.nodeID, node.seq);
                }
            }
            if (offline != null) {
                // Requester said it is OFFLINE
                if (node.offlineSince > 0) {
                    // We also knew it as offline
                    node.markAsOffline(seq);
                    continue;
                }
                if (!node.local) {
                    if (node.offlineSince == 0) {
                        // We know it is online, so we change it to offline
                        if (node.markAsOffline(seq)) {
                            // Remove remote actions and listeners
                            registry.removeActions(node.nodeID);
                            eventbus.removeListeners(node.nodeID);
                            writer.close(node.nodeID);
                            disconnectedNodes.add(node);
                        } else if (seq == node.seq) {
                            // We send back that this node is online
                            node.seq = seq + 1;
                            node.info.put("seq", node.seq);
                            if (cpuSeq < node.cpuSeq && node.cpuSeq > 0) {
                                ArrayList<Object> array = new ArrayList<>(3);
                                array.add(node.info.asObject());
                                array.add(node.cpuSeq);
                                array.add(node.cpu);
                                onlineRsp.putUnsafe(node.nodeID, array);
                            } else {
                                onlineRsp.putUnsafe(node.nodeID, Collections.singletonList(node.info.asObject()));
                            }
                        }
                    }
                    continue;
                }
            } else if (online != null) {
                // Requester said it is ONLINE
                if (node.offlineSince == 0) {
                    if (cpuSeq > node.cpuSeq) {
                        // We update our CPU info
                        node.updateCpu(cpuSeq, cpu);
                    } else if (cpuSeq < node.cpuSeq && node.cpuSeq > 0) {
                        // We have newer CPU value, send back
                        ArrayList<Object> array = new ArrayList<>(2);
                        array.add(node.cpuSeq);
                        array.add(node.cpu);
                        onlineRsp.putUnsafe(node.nodeID, array);
                    }
                } else {
                    // request it and we'll receive its INFO
                    continue;
                }
            }
        } finally {
            node.writeLock.unlock();
        }
    }
    // Create gossip response
    FastBuildTree root = new FastBuildTree(4);
    root.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
    root.putUnsafe("sender", nodeID);
    // Remove empty blocks
    boolean emptyOnlineBlock = onlineRsp.isEmpty();
    boolean emptyOfflineBlock = offlineRsp.isEmpty();
    if (emptyOnlineBlock && emptyOfflineBlock) {
        // Message is empty
        return root;
    }
    if (!emptyOnlineBlock) {
        root.putUnsafe("online", onlineRsp.asObject());
    }
    if (!emptyOfflineBlock) {
        root.putUnsafe("offline", offlineRsp.asObject());
    }
    // Debug
    if (debug) {
        logger.info("Gossip response submitting to \"" + sender + "\" node:\r\n" + root);
    }
    // Serialize response
    byte[] packet = serialize(PACKET_GOSSIP_RSP_ID, root);
    // Send response
    writer.send(sender, packet);
    // Notify listeners (unexpected disconnection)
    for (NodeDescriptor node : disconnectedNodes) {
        logger.info("Node \"" + node.nodeID + "\" disconnected.");
        broadcastNodeDisconnected(node.info, true);
    }
    // For unit testing
    return root;
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 7 with FastBuildTree

use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.

the class TcpTransporter method received.

// --- MESSAGE RECEIVED ---
public void received(byte packetID, byte[] packet) {
    executor.execute(() -> {
        // Parse message
        Tree data;
        try {
            data = serializer.read(packet);
        } catch (Exception cause) {
            logger.warn("Unable to parse incoming message!", cause);
            return;
        }
        // Send message to proper component
        try {
            switch(packetID) {
                case PACKET_EVENT_ID:
                    // Incoming event
                    if (debug) {
                        logger.info("Event message received:\r\n" + data);
                    }
                    eventbus.receiveEvent(data);
                    return;
                case PACKET_REQUEST_ID:
                    // Incoming request
                    if (debug) {
                        logger.info("Request message received:\r\n" + data);
                    }
                    registry.receiveRequest(data);
                    return;
                case PACKET_RESPONSE_ID:
                    // Incoming response
                    if (debug) {
                        logger.info("Response message received:\r\n" + data);
                    }
                    registry.receiveResponse(data);
                    return;
                case PACKET_PING_ID:
                    // Send pong
                    if (debug) {
                        logger.info("Ping message received:\r\n" + data);
                    }
                    String id = data.get("id", "");
                    if (id == null || id.isEmpty()) {
                        logger.warn("Missing \"id\" property:\r\n" + data);
                        return;
                    }
                    String sender = data.get("sender", "");
                    if (sender == null || sender.isEmpty()) {
                        logger.warn("Missing \"sender\" property:\r\n" + data);
                        return;
                    }
                    long time = data.get("time", 0L);
                    FastBuildTree msg = new FastBuildTree(5);
                    msg.putUnsafe("ver", PROTOCOL_VERSION);
                    msg.putUnsafe("sender", this.nodeID);
                    msg.putUnsafe("id", id);
                    msg.putUnsafe("received", time);
                    msg.putUnsafe("time", System.currentTimeMillis());
                    writer.send(sender, serialize(PACKET_PONG_ID, msg));
                    return;
                case PACKET_PONG_ID:
                    // Pong received
                    if (debug) {
                        logger.info("Pong message received:\r\n" + data);
                    }
                    registry.receiveResponse(data);
                    return;
                case PACKET_GOSSIP_REQ_ID:
                    // Incoming gossip request
                    processGossipRequest(data);
                    return;
                case PACKET_GOSSIP_RSP_ID:
                    // Incoming gossip request
                    processGossipResponse(data);
                    return;
                case PACKET_GOSSIP_HELLO_ID:
                    // Incoming "hello" message
                    processGossipHello(data);
                    return;
                default:
                    logger.warn("Unsupported message ID (" + packetID + ")!");
            }
        } catch (Exception cause) {
            logger.warn("Unable to process incoming message!", cause);
        }
    });
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 8 with FastBuildTree

use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.

the class TcpTransporter method generateGossipHello.

/**
 * Create Gossip HELLO packet. Hello message is invariable, so we can cache
 * it.
 */
public byte[] generateGossipHello() {
    if (cachedHelloMessage != null) {
        return cachedHelloMessage;
    }
    try {
        FastBuildTree root = new FastBuildTree(4);
        root.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
        root.putUnsafe("sender", nodeID);
        if (useHostname) {
            root.putUnsafe("host", getHostName());
        } else {
            root.putUnsafe("host", InetAddress.getLocalHost().getHostAddress());
        }
        root.putUnsafe("port", reader.getCurrentPort());
        cachedHelloMessage = serialize(PACKET_GOSSIP_HELLO_ID, root);
    } catch (Exception error) {
        throw new RuntimeException("Unable to create HELLO message!", error);
    }
    return cachedHelloMessage;
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree)

Example 9 with FastBuildTree

use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.

the class EventbusTest method putIncomingMessage.

protected void putIncomingMessage(String name, boolean broadcast, Groups groups, Tree payload) throws Exception {
    FastBuildTree msg = new FastBuildTree(6);
    msg.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
    msg.putUnsafe("sender", "node5");
    msg.putUnsafe("event", name);
    msg.putUnsafe("broadcast", broadcast);
    if (groups != null) {
        String[] array = groups.groups();
        if (array != null && array.length > 0) {
            msg.putUnsafe("groups", array);
        }
    }
    if (payload != null) {
        msg.putUnsafe("data", payload);
    }
    tr.received(tr.eventChannel, msg);
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree)

Example 10 with FastBuildTree

use of services.moleculer.util.FastBuildTree in project moleculer-java by moleculer-java.

the class TcpTransporter method unableToSend.

// --- CONNECTION ERROR ---
public void unableToSend(String nodeID, LinkedList<byte[]> packets, Throwable cause) {
    if (nodeID != null) {
        executor.execute(() -> {
            // Debug
            if (debug) {
                logger.warn("Unable to send message to \"" + nodeID + "\".", cause);
            }
            // Mark endpoint as offline
            NodeDescriptor node = nodes.get(nodeID);
            boolean disconnected = false;
            if (node != null) {
                node.writeLock.lock();
                try {
                    if (node != null && node.markAsOffline()) {
                        // Remove actions and listeners
                        registry.removeActions(nodeID);
                        eventbus.removeListeners(nodeID);
                        writer.close(node.nodeID);
                        disconnected = true;
                    }
                } catch (Exception error) {
                    logger.warn("Unable to turn off node!", error);
                } finally {
                    node.writeLock.unlock();
                }
            }
            if (node != null && disconnected) {
                // Notify listeners (unexpected disconnection)
                logger.info("Node \"" + nodeID + "\" disconnected.");
                broadcastNodeDisconnected(node.info, true);
            }
            // Send error back to the source
            if (packets != null) {
                FastBuildTree errorMap = null;
                if (cause != null) {
                    errorMap = new FastBuildTree(2);
                    // Add message
                    errorMap.putUnsafe("message", cause.getMessage());
                    // Add trace
                    StringWriter sw = new StringWriter(128);
                    PrintWriter pw = new PrintWriter(sw);
                    cause.printStackTrace(pw);
                    errorMap.putUnsafe("trace", sw.toString());
                }
                for (byte[] packet : packets) {
                    try {
                        // Remove header
                        if (packet != null && packet.length > 6) {
                            byte[] copy = new byte[packet.length - 6];
                            System.arraycopy(packet, 6, copy, 0, copy.length);
                            // Deserialize packet
                            Tree message = serializer.read(copy);
                            // Get request's unique ID
                            String id = message.get("id", (String) null);
                            if (id == null || id.isEmpty()) {
                                // Not a request
                                return;
                            }
                            // Create response message
                            FastBuildTree response = new FastBuildTree(6);
                            response.putUnsafe("id", id);
                            response.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
                            response.putUnsafe("sender", nodeID);
                            response.putUnsafe("success", false);
                            response.putUnsafe("data", (String) null);
                            if (errorMap != null) {
                                response.putUnsafe("error", errorMap);
                            }
                            registry.receiveResponse(response);
                        }
                    } catch (Exception error) {
                        logger.warn("Unable to handle error!", error);
                    }
                }
            }
        });
    }
}
Also used : StringWriter(java.io.StringWriter) FastBuildTree(services.moleculer.util.FastBuildTree) NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree) PrintWriter(java.io.PrintWriter)

Aggregations

FastBuildTree (services.moleculer.util.FastBuildTree)15 Tree (io.datatree.Tree)5 PrintWriter (java.io.PrintWriter)3 StringWriter (java.io.StringWriter)3 NodeDescriptor (services.moleculer.transporter.tcp.NodeDescriptor)3 ArrayList (java.util.ArrayList)2 LinkedList (java.util.LinkedList)2 CommonUtils.readTree (services.moleculer.util.CommonUtils.readTree)2 Annotation (java.lang.annotation.Annotation)1 Field (java.lang.reflect.Field)1 InetAddress (java.net.InetAddress)1 NetworkInterface (java.net.NetworkInterface)1 RemoteException (java.rmi.RemoteException)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 Enumeration (java.util.Enumeration)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1