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;
}
}
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;
}
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;
}
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);
}
}
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
}
}
Aggregations