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