Search in sources :

Example 1 with UniqueId

use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.

the class NioReplicationTask method drainChannel.

/**
 * The actual code which drains the channel associated with
 * the given key.  This method assumes the key has been
 * modified prior to invocation to turn off selection
 * interest in OP_READ.  When this method completes it
 * re-enables OP_READ and calls wakeup() on the selector
 * so the selector will resume watching this channel.
 */
protected void drainChannel(final SelectionKey key, ObjectReader reader) throws Exception {
    reader.setLastAccess(System.currentTimeMillis());
    reader.access();
    ReadableByteChannel channel = (ReadableByteChannel) key.channel();
    int count = -1;
    // make buffer empty
    buffer.clear();
    SocketAddress saddr = null;
    if (channel instanceof SocketChannel) {
        // loop while data available, channel is non-blocking
        while ((count = channel.read(buffer)) > 0) {
            // make buffer readable
            buffer.flip();
            if (buffer.hasArray())
                reader.append(buffer.array(), 0, count, false);
            else
                reader.append(buffer, count, false);
            // make buffer empty
            buffer.clear();
            // do we have at least one package?
            if (reader.hasPackage())
                break;
        }
    } else if (channel instanceof DatagramChannel) {
        DatagramChannel dchannel = (DatagramChannel) channel;
        saddr = dchannel.receive(buffer);
        // make buffer readable
        buffer.flip();
        if (buffer.hasArray())
            reader.append(buffer.array(), 0, buffer.limit() - buffer.position(), false);
        else
            reader.append(buffer, buffer.limit() - buffer.position(), false);
        // make buffer empty
        buffer.clear();
        // did we get a package
        count = reader.hasPackage() ? 1 : -1;
    }
    int pkgcnt = reader.count();
    if (count < 0 && pkgcnt == 0) {
        // end of stream, and no more packages to process
        remoteEof(key);
        return;
    }
    ChannelMessage[] msgs = pkgcnt == 0 ? ChannelData.EMPTY_DATA_ARRAY : reader.execute();
    // register to read new data, before we send it off to avoid dead locks
    registerForRead(key, reader);
    for (int i = 0; i < msgs.length; i++) {
        /**
         * Use send ack here if you want to ack the request to the remote
         * server before completing the request
         * This is considered an asynchronous request
         */
        if (ChannelData.sendAckAsync(msgs[i].getOptions()))
            sendAck(key, (WritableByteChannel) channel, Constants.ACK_COMMAND, saddr);
        try {
            if (Logs.MESSAGES.isTraceEnabled()) {
                try {
                    Logs.MESSAGES.trace("NioReplicationThread - Received msg:" + new UniqueId(msgs[i].getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()));
                } catch (Throwable t) {
                }
            }
            // process the message
            getCallback().messageDataReceived(msgs[i]);
            /**
             * Use send ack here if you want the request to complete on this
             * server before sending the ack to the remote server
             * This is considered a synchronized request
             */
            if (ChannelData.sendAckSync(msgs[i].getOptions()))
                sendAck(key, (WritableByteChannel) channel, Constants.ACK_COMMAND, saddr);
        } catch (RemoteProcessException e) {
            if (log.isDebugEnabled())
                log.error("Processing of cluster message failed.", e);
            if (ChannelData.sendAckSync(msgs[i].getOptions()))
                sendAck(key, (WritableByteChannel) channel, Constants.FAIL_ACK_COMMAND, saddr);
        } catch (Exception e) {
            log.error("Processing of cluster message failed.", e);
            if (ChannelData.sendAckSync(msgs[i].getOptions()))
                sendAck(key, (WritableByteChannel) channel, Constants.FAIL_ACK_COMMAND, saddr);
        }
        if (getUseBufferPool()) {
            BufferPool.getBufferPool().returnBuffer(msgs[i].getMessage());
            msgs[i].setMessage(null);
        }
    }
    if (count < 0) {
        remoteEof(key);
        return;
    }
}
Also used : ReadableByteChannel(java.nio.channels.ReadableByteChannel) SocketChannel(java.nio.channels.SocketChannel) UniqueId(org.apache.catalina.tribes.UniqueId) DatagramChannel(java.nio.channels.DatagramChannel) WritableByteChannel(java.nio.channels.WritableByteChannel) RemoteProcessException(org.apache.catalina.tribes.RemoteProcessException) CancelledKeyException(java.nio.channels.CancelledKeyException) IOException(java.io.IOException) ChannelMessage(org.apache.catalina.tribes.ChannelMessage) RemoteProcessException(org.apache.catalina.tribes.RemoteProcessException) SocketAddress(java.net.SocketAddress)

Example 2 with UniqueId

use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.

the class ParallelNioSender method doLoop.

private SendResult doLoop(long selectTimeOut, int maxAttempts, boolean waitForAck, ChannelMessage msg) throws ChannelException {
    SendResult result = new SendResult();
    int selectedKeys;
    try {
        selectedKeys = selector.select(selectTimeOut);
    } catch (IOException ioe) {
        throw new ChannelException("Parallel NIO send failed.", ioe);
    }
    if (selectedKeys == 0) {
        return result;
    }
    Iterator<SelectionKey> it = selector.selectedKeys().iterator();
    while (it.hasNext()) {
        SelectionKey sk = it.next();
        it.remove();
        int readyOps = sk.readyOps();
        sk.interestOps(sk.interestOps() & ~readyOps);
        NioSender sender = (NioSender) sk.attachment();
        try {
            if (sender.process(sk, waitForAck)) {
                sender.setComplete(true);
                result.complete(sender);
                if (Logs.MESSAGES.isTraceEnabled()) {
                    Logs.MESSAGES.trace("ParallelNioSender - Sent msg:" + new UniqueId(msg.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " to " + sender.getDestination().getName());
                }
                SenderState.getSenderState(sender.getDestination()).setReady();
            }
        // end if
        } catch (Exception x) {
            if (log.isTraceEnabled()) {
                log.trace("Error while processing send to " + sender.getDestination().getName(), x);
            }
            SenderState state = SenderState.getSenderState(sender.getDestination());
            int attempt = sender.getAttempt() + 1;
            boolean retry = (attempt <= maxAttempts && maxAttempts > 0);
            synchronized (state) {
                // sk.cancel();
                if (state.isSuspect())
                    state.setFailing();
                if (state.isReady()) {
                    state.setSuspect();
                    if (retry)
                        log.warn("Member send is failing for:" + sender.getDestination().getName() + " ; Setting to suspect and retrying.");
                    else
                        log.warn("Member send is failing for:" + sender.getDestination().getName() + " ; Setting to suspect.", x);
                }
            }
            if (!isConnected()) {
                log.warn("Not retrying send for:" + sender.getDestination().getName() + "; Sender is disconnected.");
                ChannelException cx = new ChannelException("Send failed, and sender is disconnected. Not retrying.", x);
                cx.addFaultyMember(sender.getDestination(), x);
                result.failed(cx);
                break;
            }
            byte[] data = sender.getMessage();
            if (retry) {
                try {
                    sender.disconnect();
                    sender.connect();
                    sender.setAttempt(attempt);
                    sender.setMessage(data);
                } catch (Exception ignore) {
                    state.setFailing();
                }
            } else {
                ChannelException cx = new ChannelException("Send failed, attempt:" + sender.getAttempt() + " max:" + maxAttempts, x);
                cx.addFaultyMember(sender.getDestination(), x);
                result.failed(cx);
            }
        // end if
        }
    }
    return result;
}
Also used : SelectionKey(java.nio.channels.SelectionKey) UniqueId(org.apache.catalina.tribes.UniqueId) IOException(java.io.IOException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) ChannelException(org.apache.catalina.tribes.ChannelException) SenderState(org.apache.catalina.tribes.transport.SenderState) ChannelException(org.apache.catalina.tribes.ChannelException)

Example 3 with UniqueId

use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.

the class LazyReplicatedMap method publishEntryInfo.

/**
 * publish info about a map pair (key/value) to other nodes in the cluster
 * @param key Object
 * @param value Object
 * @return Member - the backup node
 * @throws ChannelException
 */
@Override
protected Member[] publishEntryInfo(Object key, Object value) throws ChannelException {
    if (!(key instanceof Serializable && value instanceof Serializable))
        return new Member[0];
    Member[] members = getMapMembers();
    int firstIdx = getNextBackupIndex();
    int nextIdx = firstIdx;
    Member[] backup = new Member[0];
    // there are no backups
    if (members.length == 0 || firstIdx == -1)
        return backup;
    boolean success = false;
    do {
        // select a backup node
        Member next = members[nextIdx];
        // increment for the next round of back up selection
        nextIdx = nextIdx + 1;
        if (nextIdx >= members.length)
            nextIdx = 0;
        if (next == null) {
            continue;
        }
        MapMessage msg = null;
        try {
            Member[] tmpBackup = wrap(next);
            // publish the backup data to one node
            msg = new MapMessage(getMapContextName(), MapMessage.MSG_BACKUP, false, (Serializable) key, (Serializable) value, null, channel.getLocalMember(false), tmpBackup);
            if (log.isTraceEnabled())
                log.trace("Publishing backup data:" + msg + " to: " + next.getName());
            UniqueId id = getChannel().send(tmpBackup, msg, getChannelSendOptions());
            if (log.isTraceEnabled())
                log.trace("Data published:" + msg + " msg Id:" + id);
            // we published out to a backup, mark the test success
            success = true;
            backup = tmpBackup;
        } catch (ChannelException x) {
            log.error("Unable to replicate backup key:" + key + " to backup:" + next + ". Reason:" + x.getMessage(), x);
            continue;
        }
        try {
            // publish the data out to all nodes
            Member[] proxies = excludeFromSet(backup, getMapMembers());
            if (success && proxies.length > 0) {
                msg = new MapMessage(getMapContextName(), MapMessage.MSG_PROXY, false, (Serializable) key, null, null, channel.getLocalMember(false), backup);
                if (log.isTraceEnabled())
                    log.trace("Publishing proxy data:" + msg + " to: " + Arrays.toNameString(proxies));
                getChannel().send(proxies, msg, getChannelSendOptions());
            }
        } catch (ChannelException x) {
            // log the error, but proceed, this should only happen if a node went down,
            // and if the node went down, then it can't receive the message, the others
            // should still get it.
            log.error("Unable to replicate proxy key:" + key + " to backup:" + next + ". Reason:" + x.getMessage(), x);
        }
    } while (!success && (firstIdx != nextIdx));
    return backup;
}
Also used : UniqueId(org.apache.catalina.tribes.UniqueId) Serializable(java.io.Serializable) Member(org.apache.catalina.tribes.Member) ChannelException(org.apache.catalina.tribes.ChannelException)

Example 4 with UniqueId

use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.

the class GroupChannel method messageReceived.

/**
 * Callback from the interceptor stack. <br>
 * When a message is received from a remote node, this method will be invoked by
 * the previous interceptor.<br>
 * This method can also be used to send a message to other components within the same application,
 * but its an extreme case, and you're probably better off doing that logic between the applications itself.
 * @param msg ChannelMessage
 */
@Override
public void messageReceived(ChannelMessage msg) {
    if (msg == null)
        return;
    try {
        if (Logs.MESSAGES.isTraceEnabled()) {
            Logs.MESSAGES.trace("GroupChannel - Received msg:" + new UniqueId(msg.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " from " + msg.getAddress().getName());
        }
        Serializable fwd = null;
        if ((msg.getOptions() & SEND_OPTIONS_BYTE_MESSAGE) == SEND_OPTIONS_BYTE_MESSAGE) {
            fwd = new ByteMessage(msg.getMessage().getBytes());
        } else {
            try {
                fwd = XByteBuffer.deserialize(msg.getMessage().getBytesDirect(), 0, msg.getMessage().getLength());
            } catch (Exception sx) {
                log.error("Unable to deserialize message:" + msg, sx);
                return;
            }
        }
        if (Logs.MESSAGES.isTraceEnabled()) {
            Logs.MESSAGES.trace("GroupChannel - Receive Message:" + new UniqueId(msg.getUniqueId()) + " is " + fwd);
        }
        // get the actual member with the correct alive time
        Member source = msg.getAddress();
        boolean rx = false;
        boolean delivered = false;
        for (int i = 0; i < channelListeners.size(); i++) {
            ChannelListener channelListener = (ChannelListener) channelListeners.get(i);
            if (channelListener != null && channelListener.accept(fwd, source)) {
                channelListener.messageReceived(fwd, source);
                delivered = true;
                // is responsible for returning the reply, otherwise we send an absence reply
                if (channelListener instanceof RpcChannel)
                    rx = true;
            }
        }
        // for
        if ((!rx) && (fwd instanceof RpcMessage)) {
            // if we have a message that requires a response,
            // but none was given, send back an immediate one
            sendNoRpcChannelReply((RpcMessage) fwd, source);
        }
        if (Logs.MESSAGES.isTraceEnabled()) {
            Logs.MESSAGES.trace("GroupChannel delivered[" + delivered + "] id:" + new UniqueId(msg.getUniqueId()));
        }
    } catch (Exception x) {
        // as a warning.
        if (log.isWarnEnabled())
            log.warn("Error receiving message:", x);
        throw new RemoteProcessException("Exception:" + x.getMessage(), x);
    }
}
Also used : UniqueId(org.apache.catalina.tribes.UniqueId) Serializable(java.io.Serializable) ChannelListener(org.apache.catalina.tribes.ChannelListener) RemoteProcessException(org.apache.catalina.tribes.RemoteProcessException) ChannelException(org.apache.catalina.tribes.ChannelException) RemoteProcessException(org.apache.catalina.tribes.RemoteProcessException) ByteMessage(org.apache.catalina.tribes.ByteMessage) Member(org.apache.catalina.tribes.Member)

Example 5 with UniqueId

use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.

the class NonBlockingCoordinator method startElection.

// ============================================================================================================
// COORDINATION HANDLING
// ============================================================================================================
public void startElection(boolean force) throws ChannelException {
    synchronized (electionMutex) {
        MemberImpl local = (MemberImpl) getLocalMember(false);
        MemberImpl[] others = membership.getMembers();
        fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_START_ELECT, this, "Election initiated"));
        if (others.length == 0) {
            this.viewId = new UniqueId(UUIDGenerator.randomUUID(false));
            this.view = new Membership(local, AbsoluteOrder.comp, true);
            this.handleViewConf(this.createElectionMsg(local, others, local), local, view);
            // the only member, no need for an election
            return;
        }
        if (suggestedviewId != null) {
            if (view != null && Arrays.diff(view, suggestedView, local).length == 0 && Arrays.diff(suggestedView, view, local).length == 0) {
                suggestedviewId = null;
                suggestedView = null;
                fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_ELECT_ABANDONED, this, "Election abandoned, running election matches view"));
            } else {
                fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_ELECT_ABANDONED, this, "Election abandoned, election running"));
            }
            // election already running, I'm not allowed to have two of them
            return;
        }
        if (view != null && Arrays.diff(view, membership, local).length == 0 && Arrays.diff(membership, view, local).length == 0) {
            fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_ELECT_ABANDONED, this, "Election abandoned, view matches membership"));
            // already have this view installed
            return;
        }
        int prio = AbsoluteOrder.comp.compare(local, others[0]);
        // am I the leader in my view?
        MemberImpl leader = (prio < 0) ? local : others[0];
        if (local.equals(leader) || force) {
            CoordinationMessage msg = createElectionMsg(local, others, leader);
            suggestedviewId = msg.getId();
            suggestedView = new Membership(local, AbsoluteOrder.comp, true);
            Arrays.fill(suggestedView, msg.getMembers());
            fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_PROCESS_ELECT, this, "Election, sending request"));
            sendElectionMsg(local, others[0], msg);
        } else {
            try {
                coordMsgReceived.set(false);
                fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_WAIT_FOR_MSG, this, "Election, waiting for request"));
                electionMutex.wait(waitForCoordMsgTimeout);
            } catch (InterruptedException x) {
                Thread.interrupted();
            }
            if (suggestedviewId == null && (!coordMsgReceived.get())) {
                // no message arrived, send the coord msg
                // fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_WAIT_FOR_MSG,this,"Election, waiting timed out."));
                // startElection(true);
                fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_ELECT_ABANDONED, this, "Election abandoned, waiting timed out."));
            } else {
                fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_ELECT_ABANDONED, this, "Election abandoned, received a message"));
            }
        }
    // end if
    }
}
Also used : UniqueId(org.apache.catalina.tribes.UniqueId) MemberImpl(org.apache.catalina.tribes.membership.MemberImpl) Membership(org.apache.catalina.tribes.membership.Membership)

Aggregations

UniqueId (org.apache.catalina.tribes.UniqueId)19 ChannelException (org.apache.catalina.tribes.ChannelException)11 Member (org.apache.catalina.tribes.Member)9 IOException (java.io.IOException)6 Serializable (java.io.Serializable)6 RemoteProcessException (org.apache.catalina.tribes.RemoteProcessException)5 ByteMessage (org.apache.catalina.tribes.ByteMessage)4 Membership (org.apache.catalina.tribes.membership.Membership)4 ChannelMessage (org.apache.catalina.tribes.ChannelMessage)3 SocketAddress (java.net.SocketAddress)2 UnknownHostException (java.net.UnknownHostException)2 CancelledKeyException (java.nio.channels.CancelledKeyException)2 DatagramChannel (java.nio.channels.DatagramChannel)2 ReadableByteChannel (java.nio.channels.ReadableByteChannel)2 SelectionKey (java.nio.channels.SelectionKey)2 SocketChannel (java.nio.channels.SocketChannel)2 WritableByteChannel (java.nio.channels.WritableByteChannel)2 ChannelListener (org.apache.catalina.tribes.ChannelListener)2 ErrorHandler (org.apache.catalina.tribes.ErrorHandler)2 ChannelData (org.apache.catalina.tribes.io.ChannelData)2