use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.
the class OutboundMessageRegistry method registerPending.
/**
* @param allowEmpty is msg.getMessage() allowed to be null?
*/
@SuppressWarnings("unchecked")
private void registerPending(OutNetMessage msg, boolean allowEmpty) {
if ((!allowEmpty) && (msg.getMessage() == null))
throw new IllegalArgumentException("OutNetMessage doesn't contain an I2NPMessage? Impossible?");
MessageSelector sel = msg.getReplySelector();
if (sel == null)
throw new IllegalArgumentException("No reply selector? Impossible?");
if (!_activeMessages.add(msg))
// dont add dups
return;
synchronized (_selectorToMessage) {
Object oldMsg = _selectorToMessage.put(sel, msg);
if (oldMsg != null) {
List<OutNetMessage> multi = null;
if (oldMsg instanceof OutNetMessage) {
// multi = Collections.synchronizedList(new ArrayList(4));
multi = new ArrayList<OutNetMessage>(4);
multi.add((OutNetMessage) oldMsg);
multi.add(msg);
_selectorToMessage.put(sel, multi);
} else if (oldMsg instanceof List) {
multi = (List<OutNetMessage>) oldMsg;
multi.add(msg);
_selectorToMessage.put(sel, multi);
}
if (_log.shouldLog(Log.WARN))
_log.warn("a single message selector [" + sel + "] with multiple messages (" + multi + ")");
}
}
synchronized (_selectors) {
_selectors.add(sel);
}
_cleanupTask.scheduleExpiration(sel);
}
use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.
the class OutboundMessageRegistry method getOriginalMessages.
/**
* Retrieve all messages that are waiting for the specified message. In
* addition, those matches may include instructions to either continue or not
* continue waiting for further replies - if it should continue, the matched
* message remains in the registry, but if it shouldn't continue, the matched
* message is removed from the registry.
*
* This is called only by InNetMessagePool.
*
* TODO this calls isMatch() in the selectors from inside the lock, which
* can lead to deadlocks if the selector does too much in isMatch().
* Remove the lock if possible.
*
* @param message Payload received that may be a reply to something we sent
* @return non-null List of OutNetMessage describing messages that were waiting for
* the payload
*/
@SuppressWarnings("unchecked")
public List<OutNetMessage> getOriginalMessages(I2NPMessage message) {
List<MessageSelector> matchedSelectors = null;
List<MessageSelector> removedSelectors = null;
synchronized (_selectors) {
// MessageSelector sel = iter.next();
for (int i = 0; i < _selectors.size(); i++) {
MessageSelector sel = _selectors.get(i);
boolean isMatch = sel.isMatch(message);
if (isMatch) {
if (matchedSelectors == null)
matchedSelectors = new ArrayList<MessageSelector>(1);
matchedSelectors.add(sel);
if (!sel.continueMatching()) {
if (removedSelectors == null)
removedSelectors = new ArrayList<MessageSelector>(1);
removedSelectors.add(sel);
// iter.remove();
_selectors.remove(i);
i--;
}
}
}
}
List<OutNetMessage> rv;
if (matchedSelectors != null) {
rv = new ArrayList<OutNetMessage>(matchedSelectors.size());
for (MessageSelector sel : matchedSelectors) {
boolean removed = false;
OutNetMessage msg = null;
List<OutNetMessage> msgs = null;
synchronized (_selectorToMessage) {
Object o = null;
if ((removedSelectors != null) && (removedSelectors.contains(sel))) {
o = _selectorToMessage.remove(sel);
removed = true;
} else {
o = _selectorToMessage.get(sel);
}
if (o instanceof OutNetMessage) {
msg = (OutNetMessage) o;
rv.add(msg);
} else if (o instanceof List) {
msgs = (List<OutNetMessage>) o;
rv.addAll(msgs);
}
}
if (removed) {
if (msg != null) {
_activeMessages.remove(msg);
} else if (msgs != null) {
_activeMessages.removeAll(msgs);
}
}
}
} else {
rv = Collections.emptyList();
}
return rv;
}
use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.
the class TransportImpl method afterSend.
/**
* The transport is done sending this message. This is the method that actually
* does all of the cleanup - firing off jobs, requeueing, updating stats, etc.
*
* @param msg message in question
* @param sendSuccessful true if the peer received it
* @param msToSend how long it took to transfer the data to the peer
* @param allowRequeue true if we should try other transports if available
*/
protected void afterSend(OutNetMessage msg, boolean sendSuccessful, boolean allowRequeue, long msToSend) {
if (msg.getTarget() == null) {
// Bail out now as it will NPE in a dozen places below.
return;
}
boolean log = false;
if (sendSuccessful)
msg.timestamp("afterSend(successful)");
else
msg.timestamp("afterSend(failed)");
if (!sendSuccessful)
msg.transportFailed(getStyle());
if (msToSend > 1500) {
if (_log.shouldLog(Log.INFO))
_log.info(getStyle() + " afterSend slow: " + (sendSuccessful ? "success " : "FAIL ") + msg.getMessageSize() + " byte " + msg.getMessageType() + ' ' + msg.getMessageId() + " to " + msg.getTarget().getIdentity().calculateHash().toBase64().substring(0, 6) + " took " + msToSend + " ms");
}
// if (true)
// _log.error("(not error) I2NP message sent? " + sendSuccessful + " " + msg.getMessageId() + " after " + msToSend + "/" + msg.getTransmissionTime());
long lifetime = msg.getLifetime();
if (lifetime > 3000) {
int level = Log.INFO;
if (!sendSuccessful)
level = Log.DEBUG;
if (_log.shouldLog(level))
_log.log(level, getStyle() + " afterSend slow (" + (sendSuccessful ? "success " : "FAIL ") + lifetime + "/" + msToSend + "): " + msg.getMessageSize() + " byte " + msg.getMessageType() + " " + msg.getMessageId() + " from " + _context.routerHash().toBase64().substring(0, 6) + " to " + msg.getTarget().getIdentity().calculateHash().toBase64().substring(0, 6) + ": " + msg.toString());
} else {
if (_log.shouldLog(Log.INFO))
_log.info(getStyle() + " afterSend: " + (sendSuccessful ? "success " : "FAIL ") + msg.getMessageSize() + " byte " + msg.getMessageType() + " " + msg.getMessageId() + " from " + _context.routerHash().toBase64().substring(0, 6) + " to " + msg.getTarget().getIdentity().calculateHash().toBase64().substring(0, 6) + "\n" + msg.toString());
}
if (sendSuccessful) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getStyle() + " Sent " + msg.getMessageType() + " successfully to " + msg.getTarget().getIdentity().getHash().toBase64());
Job j = msg.getOnSendJob();
if (j != null)
_context.jobQueue().addJob(j);
log = true;
msg.discardData();
} else {
if (_log.shouldLog(Log.INFO))
_log.info(getStyle() + " Failed to send " + msg.getMessageType() + " to " + msg.getTarget().getIdentity().getHash().toBase64() + " (details: " + msg + ')');
if (msg.getExpiration() < _context.clock().now())
_context.statManager().addRateData("transport.expiredOnQueueLifetime", lifetime);
if (allowRequeue) {
if (((msg.getExpiration() <= 0) || (msg.getExpiration() > _context.clock().now())) && (msg.getMessage() != null)) {
// this may not be the last transport available - keep going
_context.outNetMessagePool().add(msg);
// don't discard the data yet!
} else {
if (_log.shouldLog(Log.INFO))
_log.info("No more time left (" + new Date(msg.getExpiration()) + ", expiring without sending successfully the " + msg.getMessageType());
if (msg.getOnFailedSendJob() != null)
_context.jobQueue().addJob(msg.getOnFailedSendJob());
MessageSelector selector = msg.getReplySelector();
if (selector != null) {
_context.messageRegistry().unregisterPending(msg);
}
log = true;
msg.discardData();
}
} else {
MessageSelector selector = msg.getReplySelector();
if (_log.shouldLog(Log.INFO))
_log.info("Failed and no requeue allowed for a " + msg.getMessageSize() + " byte " + msg.getMessageType() + " message with selector " + selector, new Exception("fail cause"));
if (msg.getOnFailedSendJob() != null)
_context.jobQueue().addJob(msg.getOnFailedSendJob());
if (msg.getOnFailedReplyJob() != null)
_context.jobQueue().addJob(msg.getOnFailedReplyJob());
if (selector != null)
_context.messageRegistry().unregisterPending(msg);
log = true;
msg.discardData();
}
}
if (log) {
/*
String type = msg.getMessageType();
// the udp transport logs some further details
_context.messageHistory().sendMessage(type, msg.getMessageId(),
msg.getExpiration(),
msg.getTarget().getIdentity().getHash(),
sendSuccessful);
*/
}
long now = _context.clock().now();
long sendTime = now - msg.getSendBegin();
long allTime = now - msg.getCreated();
if (allTime > 5 * 1000) {
if (_log.shouldLog(Log.INFO))
_log.info("Took too long from preparation to afterSend(ok? " + sendSuccessful + "): " + allTime + "ms/" + sendTime + "ms after failing on: " + msg.getFailedTransports() + " and succeeding on " + getStyle());
if ((allTime > 60 * 1000) && (sendSuccessful)) {
// VERY slow
if (_log.shouldLog(Log.WARN))
_log.warn("Severe latency? More than a minute slow? " + msg.getMessageType() + " of id " + msg.getMessageId() + " (send begin on " + new Date(msg.getSendBegin()) + " / created on " + new Date(msg.getCreated()) + "): " + msg);
_context.messageHistory().messageProcessingError(msg.getMessageId(), msg.getMessageType(), "Took too long to send [" + allTime + "ms]");
}
}
if (sendSuccessful) {
// TODO fix this stat for SSU ticket #698
_context.statManager().addRateData("transport.sendProcessingTime", lifetime);
// object churn. 33 ms for NTCP and 788 for SSU, but meaningless due to
// differences in how it's computed (immediate vs. round trip)
// _context.statManager().addRateData("transport.sendProcessingTime." + getStyle(), lifetime, 0);
_context.profileManager().messageSent(msg.getTarget().getIdentity().getHash(), getStyle(), sendTime, msg.getMessageSize());
_context.statManager().addRateData("transport.sendMessageSize", msg.getMessageSize(), sendTime);
} else {
_context.profileManager().messageFailed(msg.getTarget().getIdentity().getHash(), getStyle());
_context.statManager().addRateData("transport.sendMessageFailureLifetime", lifetime);
}
}
use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.
the class OutboundMessageRegistry method unregisterPending.
/**
* @param msg may be be null
*/
@SuppressWarnings("unchecked")
public void unregisterPending(OutNetMessage msg) {
if (msg == null)
return;
MessageSelector sel = msg.getReplySelector();
boolean stillActive = false;
synchronized (_selectorToMessage) {
Object old = _selectorToMessage.remove(sel);
if (old != null) {
if (old instanceof List) {
List<OutNetMessage> l = (List<OutNetMessage>) old;
l.remove(msg);
if (!l.isEmpty()) {
_selectorToMessage.put(sel, l);
stillActive = true;
}
}
}
}
if (!stillActive)
synchronized (_selectors) {
_selectors.remove(sel);
}
_activeMessages.remove(msg);
}
use of net.i2p.router.MessageSelector in project i2p.i2p by i2p.
the class GetBidsJob method fail.
static void fail(RouterContext context, OutNetMessage msg) {
if (msg.getOnFailedSendJob() != null) {
context.jobQueue().addJob(msg.getOnFailedSendJob());
}
if (msg.getOnFailedReplyJob() != null) {
context.jobQueue().addJob(msg.getOnFailedReplyJob());
}
MessageSelector selector = msg.getReplySelector();
if (selector != null) {
context.messageRegistry().unregisterPending(msg);
}
context.profileManager().messageFailed(msg.getTarget().getIdentity().getHash());
msg.discardData();
}
Aggregations