Search in sources :

Example 1 with DirectReplyMessage

use of org.apache.geode.internal.cache.DirectReplyMessage in project geode by apache.

the class DirectChannel method sendToMany.

/**
   * Sends a msg to a list of destinations. This code does some special optimizations to stream
   * large messages
   * 
   * @param mgr - the membership manager
   * @param p_destinations - the list of addresses to send the message to.
   * @param msg - the message to send
   * @param ackWaitThreshold
   * @param ackSAThreshold the severe alert threshold
   * @return number of bytes sent
   * @throws ConnectExceptions if message could not be send to its <code>destination</code>
   * @throws NotSerializableException If the msg cannot be serialized
   */
private int sendToMany(final MembershipManager mgr, InternalDistributedMember[] p_destinations, final DistributionMessage msg, long ackWaitThreshold, long ackSAThreshold) throws ConnectExceptions, NotSerializableException {
    InternalDistributedMember[] destinations = p_destinations;
    // Collects connect exceptions that happened during previous attempts to send.
    // These represent members we are not able to distribute to.
    ConnectExceptions failedCe = null;
    // Describes the destinations that we need to retry the send to.
    ConnectExceptions retryInfo = null;
    int bytesWritten = 0;
    boolean retry = false;
    final boolean orderedMsg = msg.orderedDelivery() || Connection.isDominoThread();
    // Connections we actually sent messages to.
    final List totalSentCons = new ArrayList(destinations.length);
    boolean interrupted = false;
    long ackTimeout = 0;
    long ackSDTimeout = 0;
    long startTime = 0;
    final DirectReplyMessage directMsg;
    if (msg instanceof DirectReplyMessage) {
        directMsg = (DirectReplyMessage) msg;
    } else {
        directMsg = null;
    }
    if (directMsg != null || msg.getProcessorId() > 0) {
        ackTimeout = (int) (ackWaitThreshold * 1000);
        if (msg.isSevereAlertCompatible() || ReplyProcessor21.isSevereAlertProcessingForced()) {
            ackSDTimeout = (int) (ackSAThreshold * 1000);
            if (ReplyProcessor21.getShortSevereAlertProcessing()) {
                ackSDTimeout = (int) (ReplyProcessor21.PR_SEVERE_ALERT_RATIO * ackSDTimeout);
            }
        }
    }
    boolean directReply = false;
    if (directMsg != null && directMsg.supportsDirectAck() && threadOwnsResources()) {
        directReply = true;
    }
    // use a regular reply processor.
    if (!directReply && directMsg != null) {
        directMsg.registerProcessor();
    }
    try {
        do {
            interrupted = interrupted || Thread.interrupted();
            /**
         * Exceptions that happened during one attempt to send
         */
            if (retryInfo != null) {
                // need to retry to each of the guys in the exception
                List retryMembers = retryInfo.getMembers();
                InternalDistributedMember[] retryDest = new InternalDistributedMember[retryMembers.size()];
                retryDest = (InternalDistributedMember[]) retryMembers.toArray(retryDest);
                destinations = retryDest;
                retryInfo = null;
                retry = true;
            }
            final List cons = new ArrayList(destinations.length);
            ConnectExceptions ce = getConnections(mgr, msg, destinations, orderedMsg, retry, ackTimeout, ackSDTimeout, cons);
            if (directReply && msg.getProcessorId() > 0) {
                // no longer a direct-reply message?
                directReply = false;
            }
            if (ce != null) {
                if (failedCe != null) {
                    failedCe.getMembers().addAll(ce.getMembers());
                    failedCe.getCauses().addAll(ce.getCauses());
                } else {
                    failedCe = ce;
                }
                ce = null;
            }
            if (cons.isEmpty()) {
                if (failedCe != null) {
                    throw failedCe;
                }
                return bytesWritten;
            }
            boolean sendingToGroup = cons.size() > 1;
            Connection permissionCon = null;
            if (sendingToGroup) {
                acquireGroupSendPermission(orderedMsg);
            } else {
                // sending to just one guy
                permissionCon = (Connection) cons.get(0);
                if (permissionCon != null) {
                    try {
                        permissionCon.acquireSendPermission();
                    } catch (ConnectionException conEx) {
                        // Set retryInfo and then retry.
                        // We want to keep calling TCPConduit.getConnection until it doesn't
                        // return a connection.
                        retryInfo = new ConnectExceptions();
                        retryInfo.addFailure(permissionCon.getRemoteAddress(), conEx);
                        continue;
                    }
                }
            }
            try {
                if (logger.isDebugEnabled()) {
                    logger.debug("{}{}) to {} peers ({}) via tcp/ip", (retry ? "Retrying send (" : "Sending ("), msg, cons.size(), cons);
                }
                DMStats stats = getDMStats();
                // used for cons we sent to this time
                List<?> sentCons;
                final BaseMsgStreamer ms = MsgStreamer.create(cons, msg, directReply, stats);
                try {
                    startTime = 0;
                    if (ackTimeout > 0) {
                        startTime = System.currentTimeMillis();
                    }
                    ms.reserveConnections(startTime, ackTimeout, ackSDTimeout);
                    int result = ms.writeMessage();
                    if (bytesWritten == 0) {
                        // bytesWritten only needs to be set once.
                        // if we have to do a retry we don't want to count
                        // each one's bytes.
                        bytesWritten = result;
                    }
                    ce = ms.getConnectExceptions();
                    sentCons = ms.getSentConnections();
                    totalSentCons.addAll(sentCons);
                } catch (NotSerializableException e) {
                    throw e;
                } catch (ToDataException e) {
                    throw e;
                } catch (IOException ex) {
                    throw new InternalGemFireException(LocalizedStrings.DirectChannel_UNKNOWN_ERROR_SERIALIZING_MESSAGE.toLocalizedString(), ex);
                } finally {
                    try {
                        ms.close();
                    } catch (IOException e) {
                        throw new InternalGemFireException("Unknown error serializing message", e);
                    }
                }
                if (ce != null) {
                    retryInfo = ce;
                    ce = null;
                }
                if (directReply && !sentCons.isEmpty()) {
                    long readAckStart = 0;
                    if (stats != null) {
                        readAckStart = stats.startReplyWait();
                    }
                    try {
                        ce = readAcks(sentCons, startTime, ackTimeout, ackSDTimeout, ce, directMsg.getDirectReplyProcessor());
                    } finally {
                        if (stats != null) {
                            stats.endReplyWait(readAckStart, startTime);
                        }
                    }
                }
            } finally {
                if (sendingToGroup) {
                    releaseGroupSendPermission(orderedMsg);
                } else if (permissionCon != null) {
                    permissionCon.releaseSendPermission();
                }
            }
            if (ce != null) {
                if (retryInfo != null) {
                    retryInfo.getMembers().addAll(ce.getMembers());
                    retryInfo.getCauses().addAll(ce.getCauses());
                } else {
                    retryInfo = ce;
                }
                ce = null;
            }
            if (retryInfo != null) {
                this.conduit.getCancelCriterion().checkCancelInProgress(null);
            }
        } while (retryInfo != null);
    } finally {
        if (interrupted) {
            Thread.currentThread().interrupt();
        }
        for (Iterator it = totalSentCons.iterator(); it.hasNext(); ) {
            Connection con = (Connection) it.next();
            con.setInUse(false, 0, 0, 0, null);
        }
    }
    if (failedCe != null) {
        throw failedCe;
    }
    return bytesWritten;
}
Also used : IOException(java.io.IOException) DirectReplyMessage(org.apache.geode.internal.cache.DirectReplyMessage) NotSerializableException(java.io.NotSerializableException) InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember)

Example 2 with DirectReplyMessage

use of org.apache.geode.internal.cache.DirectReplyMessage in project geode by apache.

the class DirectChannel method getConnections.

/**
   * Obtain the connections needed to transmit a message. The connections are put into the cons
   * object (the last parameter)
   * 
   * @param mgr the membership manager
   * @param msg the message to send
   * @param destinations who to send the message to
   * @param preserveOrder true if the msg should ordered
   * @param retry whether this is a retransmission
   * @param ackTimeout the ack warning timeout
   * @param ackSDTimeout the ack severe alert timeout
   * @param cons a list to hold the connections
   * @return null if everything went okay, or a ConnectExceptions object if some connections
   *         couldn't be obtained
   */
private ConnectExceptions getConnections(MembershipManager mgr, DistributionMessage msg, InternalDistributedMember[] destinations, boolean preserveOrder, boolean retry, long ackTimeout, long ackSDTimeout, List cons) {
    ConnectExceptions ce = null;
    for (int i = 0; i < destinations.length; i++) {
        InternalDistributedMember destination = destinations[i];
        if (destination == null) {
            continue;
        }
        if (localAddr.equals(destination)) {
            // it here either.
            continue;
        }
        if (!mgr.memberExists(destination) || mgr.shutdownInProgress() || mgr.isShunned(destination)) {
            // This should only happen if the member is no longer in the view.
            if (logger.isTraceEnabled(LogMarker.DM)) {
                logger.trace(LogMarker.DM, "Not a member: {}", destination);
            }
            if (ce == null)
                ce = new ConnectExceptions();
            ce.addFailure(destination, new ShunnedMemberException(LocalizedStrings.DirectChannel_SHUNNING_0.toLocalizedString(destination)));
        } else {
            try {
                long startTime = 0;
                if (ackTimeout > 0) {
                    startTime = System.currentTimeMillis();
                }
                Connection con = conduit.getConnection(destination, preserveOrder, retry, startTime, ackTimeout, ackSDTimeout);
                // fix for bug#37657
                con.setInUse(true, startTime, 0, 0, null);
                cons.add(con);
                if (con.isSharedResource() && msg instanceof DirectReplyMessage) {
                    DirectReplyMessage directMessage = (DirectReplyMessage) msg;
                    directMessage.registerProcessor();
                }
            } catch (IOException ex) {
                if (ce == null)
                    ce = new ConnectExceptions();
                ce.addFailure(destination, ex);
            }
        }
    }
    // for
    return ce;
}
Also used : InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember) IOException(java.io.IOException) DirectReplyMessage(org.apache.geode.internal.cache.DirectReplyMessage)

Example 3 with DirectReplyMessage

use of org.apache.geode.internal.cache.DirectReplyMessage in project geode by apache.

the class JGroupsMessenger method createJGMessage.

/**
   * This is the constructor to use to create a JGroups message holding a GemFire
   * DistributionMessage. It sets the appropriate flags in the Message and properly serializes the
   * DistributionMessage for the recipient's product version
   * 
   * @param gfmsg the DistributionMessage
   * @param src the sender address
   * @param version the version of the recipient
   * @return the new message
   */
Message createJGMessage(DistributionMessage gfmsg, JGAddress src, short version) {
    if (gfmsg instanceof DirectReplyMessage) {
        ((DirectReplyMessage) gfmsg).registerProcessor();
    }
    Message msg = new Message();
    msg.setDest(null);
    msg.setSrc(src);
    setMessageFlags(gfmsg, msg);
    try {
        long start = services.getStatistics().startMsgSerialization();
        HeapDataOutputStream out_stream = new HeapDataOutputStream(Version.fromOrdinalOrCurrent(version));
        Version.CURRENT.writeOrdinal(out_stream, true);
        if (encrypt != null) {
            out_stream.writeBoolean(true);
            writeEncryptedMessage(gfmsg, version, out_stream);
        } else {
            out_stream.writeBoolean(false);
            serializeMessage(gfmsg, out_stream);
        }
        msg.setBuffer(out_stream.toByteArray());
        services.getStatistics().endMsgSerialization(start);
    } catch (IOException | GemFireIOException ex) {
        logger.warn("Error serializing message", ex);
        if (ex instanceof GemFireIOException) {
            throw (GemFireIOException) ex;
        } else {
            GemFireIOException ioe = new GemFireIOException("Error serializing message");
            ioe.initCause(ex);
            throw ioe;
        }
    } catch (Exception ex) {
        logger.warn("Error serializing message", ex);
        GemFireIOException ioe = new GemFireIOException("Error serializing message");
        ioe.initCause(ex.getCause());
        throw ioe;
    }
    return msg;
}
Also used : DistributionMessage(org.apache.geode.distributed.internal.DistributionMessage) JoinRequestMessage(org.apache.geode.distributed.internal.membership.gms.messages.JoinRequestMessage) DirectReplyMessage(org.apache.geode.internal.cache.DirectReplyMessage) JoinResponseMessage(org.apache.geode.distributed.internal.membership.gms.messages.JoinResponseMessage) LocalizedMessage(org.apache.geode.internal.logging.log4j.LocalizedMessage) Message(org.jgroups.Message) HighPriorityDistributionMessage(org.apache.geode.distributed.internal.HighPriorityDistributionMessage) HeapDataOutputStream(org.apache.geode.internal.HeapDataOutputStream) GemFireIOException(org.apache.geode.GemFireIOException) GemFireIOException(org.apache.geode.GemFireIOException) IOException(java.io.IOException) MemberShunnedException(org.apache.geode.internal.tcp.MemberShunnedException) DistributedSystemDisconnectedException(org.apache.geode.distributed.DistributedSystemDisconnectedException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ForcedDisconnectException(org.apache.geode.ForcedDisconnectException) GemFireIOException(org.apache.geode.GemFireIOException) SystemConnectException(org.apache.geode.SystemConnectException) GemFireConfigException(org.apache.geode.GemFireConfigException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) DirectReplyMessage(org.apache.geode.internal.cache.DirectReplyMessage)

Example 4 with DirectReplyMessage

use of org.apache.geode.internal.cache.DirectReplyMessage in project geode by apache.

the class JGroupsMessenger method send.

private Set<InternalDistributedMember> send(DistributionMessage msg, boolean reliably) {
    // perform the same jgroups messaging as in 8.2's GMSMembershipManager.send() method
    // BUT: when marshalling messages we need to include the version of the product and
    // localAddress at the beginning of the message. These should be used in the receiver
    // code to create a versioned input stream, read the sender address, then read the message
    // and set its sender address
    DMStats theStats = services.getStatistics();
    NetView oldView = this.view;
    if (!myChannel.isConnected()) {
        logger.info("JGroupsMessenger channel is closed - messaging is not possible");
        throw new DistributedSystemDisconnectedException("Distributed System is shutting down");
    }
    filterOutgoingMessage(msg);
    // the message's processor if necessary
    if ((msg instanceof DirectReplyMessage) && msg.isDirectAck() && msg.getProcessorId() <= 0) {
        ((DirectReplyMessage) msg).registerProcessor();
    }
    InternalDistributedMember[] destinations = msg.getRecipients();
    boolean allDestinations = msg.forAll();
    boolean useMcast = false;
    if (services.getConfig().getTransport().isMcastEnabled()) {
        if (msg.getMulticast() || allDestinations) {
            useMcast = services.getManager().isMulticastAllowed();
        }
    }
    if (logger.isDebugEnabled() && reliably) {
        String recips = useMcast ? "multicast" : Arrays.toString(msg.getRecipients());
        logger.debug("sending via JGroups: [{}] recipients: {}", msg, recips);
    }
    JGAddress local = this.jgAddress;
    if (useMcast) {
        long startSer = theStats.startMsgSerialization();
        Message jmsg = createJGMessage(msg, local, Version.CURRENT_ORDINAL);
        theStats.endMsgSerialization(startSer);
        Exception problem;
        try {
            jmsg.setTransientFlag(TransientFlag.DONT_LOOPBACK);
            if (!reliably) {
                jmsg.setFlag(Message.Flag.NO_RELIABILITY);
            }
            theStats.incSentBytes(jmsg.getLength());
            logger.trace("Sending JGroups message: {}", jmsg);
            myChannel.send(jmsg);
        } catch (Exception e) {
            logger.debug("caught unexpected exception", e);
            Throwable cause = e.getCause();
            if (cause instanceof ForcedDisconnectException) {
                problem = (Exception) cause;
            } else {
                problem = e;
            }
            if (services.getShutdownCause() != null) {
                Throwable shutdownCause = services.getShutdownCause();
                // problem.
                if (shutdownCause instanceof ForcedDisconnectException) {
                    problem = (Exception) shutdownCause;
                } else {
                    Throwable ne = problem;
                    while (ne.getCause() != null) {
                        ne = ne.getCause();
                    }
                    ne.initCause(services.getShutdownCause());
                }
            }
            final String channelClosed = LocalizedStrings.GroupMembershipService_CHANNEL_CLOSED.toLocalizedString();
            // services.getManager().membershipFailure(channelClosed, problem);
            throw new DistributedSystemDisconnectedException(channelClosed, problem);
        }
    } else // useMcast
    {
        // ! useMcast
        int len = destinations.length;
        // explicit list of members
        List<GMSMember> calculatedMembers;
        // == calculatedMembers.len
        int calculatedLen;
        if (len == 1 && destinations[0] == DistributionMessage.ALL_RECIPIENTS) {
            // send to all
            // Grab a copy of the current membership
            NetView v = services.getJoinLeave().getView();
            // Construct the list
            calculatedLen = v.size();
            calculatedMembers = new LinkedList<GMSMember>();
            for (int i = 0; i < calculatedLen; i++) {
                InternalDistributedMember m = (InternalDistributedMember) v.get(i);
                calculatedMembers.add((GMSMember) m.getNetMember());
            }
        } else // send to all
        {
            // send to explicit list
            calculatedLen = len;
            calculatedMembers = new LinkedList<GMSMember>();
            for (int i = 0; i < calculatedLen; i++) {
                calculatedMembers.add((GMSMember) destinations[i].getNetMember());
            }
        }
        // send to explicit list
        Int2ObjectOpenHashMap<Message> messages = new Int2ObjectOpenHashMap<>();
        long startSer = theStats.startMsgSerialization();
        boolean firstMessage = true;
        for (GMSMember mbr : calculatedMembers) {
            short version = mbr.getVersionOrdinal();
            if (!messages.containsKey(version)) {
                Message jmsg = createJGMessage(msg, local, version);
                messages.put(version, jmsg);
                if (firstMessage) {
                    theStats.incSentBytes(jmsg.getLength());
                    firstMessage = false;
                }
            }
        }
        theStats.endMsgSerialization(startSer);
        Collections.shuffle(calculatedMembers);
        int i = 0;
        for (GMSMember mbr : calculatedMembers) {
            JGAddress to = new JGAddress(mbr);
            short version = mbr.getVersionOrdinal();
            Message jmsg = messages.get(version);
            Exception problem = null;
            try {
                Message tmp = (i < (calculatedLen - 1)) ? jmsg.copy(true) : jmsg;
                if (!reliably) {
                    jmsg.setFlag(Message.Flag.NO_RELIABILITY);
                }
                tmp.setDest(to);
                tmp.setSrc(this.jgAddress);
                logger.trace("Unicasting to {}", to);
                myChannel.send(tmp);
            } catch (Exception e) {
                problem = e;
            }
            if (problem != null) {
                Throwable cause = services.getShutdownCause();
                if (cause != null) {
                    // problem.
                    if (cause instanceof ForcedDisconnectException) {
                        problem = (Exception) cause;
                    } else {
                        Throwable ne = problem;
                        while (ne.getCause() != null) {
                            ne = ne.getCause();
                        }
                        ne.initCause(cause);
                    }
                }
                final String channelClosed = LocalizedStrings.GroupMembershipService_CHANNEL_CLOSED.toLocalizedString();
                // services.getManager().membershipFailure(channelClosed, problem);
                throw new DistributedSystemDisconnectedException(channelClosed, problem);
            }
        }
    // send individually
    }
    // (i.e., left the view), we signal it here.
    if (msg.forAll()) {
        return Collections.emptySet();
    }
    Set<InternalDistributedMember> result = new HashSet<>();
    NetView newView = this.view;
    if (newView != null && newView != oldView) {
        for (InternalDistributedMember d : destinations) {
            if (!newView.contains(d)) {
                logger.debug("messenger: member has left the view: {}  view is now {}", d, newView);
                result.add(d);
            }
        }
    }
    return result;
}
Also used : Int2ObjectOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap) DMStats(org.apache.geode.distributed.internal.DMStats) DistributedSystemDisconnectedException(org.apache.geode.distributed.DistributedSystemDisconnectedException) DistributionMessage(org.apache.geode.distributed.internal.DistributionMessage) JoinRequestMessage(org.apache.geode.distributed.internal.membership.gms.messages.JoinRequestMessage) DirectReplyMessage(org.apache.geode.internal.cache.DirectReplyMessage) JoinResponseMessage(org.apache.geode.distributed.internal.membership.gms.messages.JoinResponseMessage) LocalizedMessage(org.apache.geode.internal.logging.log4j.LocalizedMessage) Message(org.jgroups.Message) HighPriorityDistributionMessage(org.apache.geode.distributed.internal.HighPriorityDistributionMessage) ForcedDisconnectException(org.apache.geode.ForcedDisconnectException) GMSMember(org.apache.geode.distributed.internal.membership.gms.GMSMember) NetView(org.apache.geode.distributed.internal.membership.NetView) MemberShunnedException(org.apache.geode.internal.tcp.MemberShunnedException) DistributedSystemDisconnectedException(org.apache.geode.distributed.DistributedSystemDisconnectedException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ForcedDisconnectException(org.apache.geode.ForcedDisconnectException) GemFireIOException(org.apache.geode.GemFireIOException) SystemConnectException(org.apache.geode.SystemConnectException) GemFireConfigException(org.apache.geode.GemFireConfigException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) DirectReplyMessage(org.apache.geode.internal.cache.DirectReplyMessage) InternalDistributedMember(org.apache.geode.distributed.internal.membership.InternalDistributedMember) HashSet(java.util.HashSet)

Aggregations

IOException (java.io.IOException)4 DirectReplyMessage (org.apache.geode.internal.cache.DirectReplyMessage)4 InternalDistributedMember (org.apache.geode.distributed.internal.membership.InternalDistributedMember)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 UnknownHostException (java.net.UnknownHostException)2 ForcedDisconnectException (org.apache.geode.ForcedDisconnectException)2 GemFireConfigException (org.apache.geode.GemFireConfigException)2 GemFireIOException (org.apache.geode.GemFireIOException)2 SystemConnectException (org.apache.geode.SystemConnectException)2 DistributedSystemDisconnectedException (org.apache.geode.distributed.DistributedSystemDisconnectedException)2 DistributionMessage (org.apache.geode.distributed.internal.DistributionMessage)2 HighPriorityDistributionMessage (org.apache.geode.distributed.internal.HighPriorityDistributionMessage)2 JoinRequestMessage (org.apache.geode.distributed.internal.membership.gms.messages.JoinRequestMessage)2 JoinResponseMessage (org.apache.geode.distributed.internal.membership.gms.messages.JoinResponseMessage)2 LocalizedMessage (org.apache.geode.internal.logging.log4j.LocalizedMessage)2 MemberShunnedException (org.apache.geode.internal.tcp.MemberShunnedException)2 Message (org.jgroups.Message)2 Int2ObjectOpenHashMap (it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap)1 NotSerializableException (java.io.NotSerializableException)1 HashSet (java.util.HashSet)1