use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.
the class GroupChannel method send.
/**
* @param destination Member[] - destination.length > 0
* @param msg Serializable - the message to send
* @param options int - sender options, options can trigger guarantee levels and different interceptors to
* react to the message see class documentation for the <code>Channel</code> object.<br>
* @param handler - callback object for error handling and completion notification, used when a message is
* sent asynchronously using the <code>Channel.SEND_OPTIONS_ASYNCHRONOUS</code> flag enabled.
* @return UniqueId - the unique Id that was assigned to this message
* @throws ChannelException - if an error occurs processing the message
* @see org.apache.catalina.tribes.Channel
*/
@Override
public UniqueId send(Member[] destination, Serializable msg, int options, ErrorHandler handler) throws ChannelException {
if (msg == null)
throw new ChannelException("Cant send a NULL message");
XByteBuffer buffer = null;
try {
if (destination == null || destination.length == 0)
throw new ChannelException("No destination given");
// generates a unique Id
ChannelData data = new ChannelData(true);
data.setAddress(getLocalMember(false));
data.setTimestamp(System.currentTimeMillis());
byte[] b = null;
if (msg instanceof ByteMessage) {
b = ((ByteMessage) msg).getMessage();
options = options | SEND_OPTIONS_BYTE_MESSAGE;
} else {
b = XByteBuffer.serialize(msg);
options = options & (~SEND_OPTIONS_BYTE_MESSAGE);
}
data.setOptions(options);
// XByteBuffer buffer = new XByteBuffer(b.length+128,false);
buffer = BufferPool.getBufferPool().getBuffer(b.length + 128, false);
buffer.append(b, 0, b.length);
data.setMessage(buffer);
InterceptorPayload payload = null;
if (handler != null) {
payload = new InterceptorPayload();
payload.setErrorHandler(handler);
}
getFirstInterceptor().sendMessage(destination, data, payload);
if (Logs.MESSAGES.isTraceEnabled()) {
Logs.MESSAGES.trace("GroupChannel - Sent msg:" + new UniqueId(data.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis()) + " to " + Arrays.toNameString(destination));
Logs.MESSAGES.trace("GroupChannel - Send Message:" + new UniqueId(data.getUniqueId()) + " is " + msg);
}
return new UniqueId(data.getUniqueId());
} catch (Exception x) {
if (x instanceof ChannelException)
throw (ChannelException) x;
throw new ChannelException(x);
} finally {
if (buffer != null)
BufferPool.getBufferPool().returnBuffer(buffer);
}
}
use of org.apache.catalina.tribes.UniqueId in project tomcat70 by apache.
the class RpcChannel method messageReceived.
@Override
public void messageReceived(Serializable msg, Member sender) {
RpcMessage rmsg = (RpcMessage) msg;
RpcCollectorKey key = new RpcCollectorKey(rmsg.uuid);
if (rmsg.reply) {
RpcCollector collector = responseMap.get(key);
if (collector == null) {
if (!(rmsg instanceof RpcMessage.NoRpcChannelReply))
callback.leftOver(rmsg.message, sender);
} else {
synchronized (collector) {
// make sure it hasn't been removed
if (responseMap.containsKey(key)) {
if ((rmsg instanceof RpcMessage.NoRpcChannelReply))
collector.destcnt--;
else
collector.addResponse(rmsg.message, sender);
if (collector.isComplete())
collector.notifyAll();
} else {
if (!(rmsg instanceof RpcMessage.NoRpcChannelReply))
callback.leftOver(rmsg.message, sender);
}
}
// synchronized
}
// end if
} else {
boolean finished = false;
final ExtendedRpcCallback excallback = (callback instanceof ExtendedRpcCallback) ? ((ExtendedRpcCallback) callback) : null;
boolean asyncReply = ((replyMessageOptions & Channel.SEND_OPTIONS_ASYNCHRONOUS) == Channel.SEND_OPTIONS_ASYNCHRONOUS);
Serializable reply = callback.replyRequest(rmsg.message, sender);
ErrorHandler handler = null;
final Serializable request = msg;
final Serializable response = reply;
final Member fsender = sender;
if (excallback != null && asyncReply) {
handler = new ErrorHandler() {
@Override
public void handleError(ChannelException x, UniqueId id) {
excallback.replyFailed(request, response, fsender, x);
}
@Override
public void handleCompletion(UniqueId id) {
excallback.replySucceeded(request, response, fsender);
}
};
}
rmsg.reply = true;
rmsg.message = reply;
try {
if (handler != null) {
channel.send(new Member[] { sender }, rmsg, replyMessageOptions & ~Channel.SEND_OPTIONS_SYNCHRONIZED_ACK, handler);
} else {
channel.send(new Member[] { sender }, rmsg, replyMessageOptions & ~Channel.SEND_OPTIONS_SYNCHRONIZED_ACK);
}
finished = true;
} catch (Exception x) {
if (excallback != null && !asyncReply) {
excallback.replyFailed(rmsg.message, reply, sender, x);
} else {
log.error("Unable to send back reply in RpcChannel.", x);
}
}
if (finished && excallback != null && !asyncReply) {
excallback.replySucceeded(rmsg.message, reply, sender);
}
}
// end if
}
use of org.apache.catalina.tribes.UniqueId in project tomcat 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 Cluster error
*/
@Override
protected Member[] publishEntryInfo(Object key, Object value) throws ChannelException {
Log log = getLog();
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(sm.getString("lazyReplicatedMap.unableReplicate.backup", key, next, 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(sm.getString("lazyReplicatedMap.unableReplicate.proxy", key, next, x.getMessage()), x);
}
} while (!success && (firstIdx != nextIdx));
return backup;
}
use of org.apache.catalina.tribes.UniqueId in project tomcat by apache.
the class NonBlockingCoordinator method startElection.
// ============================================================================================================
// COORDINATION HANDLING
// ============================================================================================================
public void startElection(boolean force) throws ChannelException {
synchronized (electionMutex) {
Member local = getLocalMember(false);
Member[] 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(createElectionMsg(local, others, 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?
Member 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.currentThread().interrupt();
}
String msg;
if (suggestedviewId == null && !coordMsgReceived.get()) {
if (Thread.interrupted()) {
msg = "Election abandoned, waiting interrupted.";
} else {
msg = "Election abandoned, waiting timed out.";
}
} else {
msg = "Election abandoned, received a message";
}
fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_ELECT_ABANDONED, this, msg));
}
}
}
Aggregations