use of net.i2p.router.Job in project i2p.i2p by i2p.
the class JobQueueHelper method renderStatusHTML.
/**
* Moved from JobQueue
* @since 0.8.9
*/
private void renderStatusHTML(Writer out) throws IOException {
List<Job> readyJobs = new ArrayList<Job>(8);
List<Job> timedJobs = new ArrayList<Job>(128);
List<Job> activeJobs = new ArrayList<Job>(8);
List<Job> justFinishedJobs = new ArrayList<Job>(8);
int numRunners = _context.jobQueue().getJobs(readyJobs, timedJobs, activeJobs, justFinishedJobs);
StringBuilder buf = new StringBuilder(32 * 1024);
buf.append("<div class=\"joblog\">").append("<h2 id=\"jobrunners\">").append(_t("Job runners")).append(": ").append(numRunners).append("</h2>\n");
long now = _context.clock().now();
buf.append("<h3 id=\"activejobs\">").append(_t("Active jobs")).append(": ").append(activeJobs.size()).append("</h3><ol>");
for (int i = 0; i < activeJobs.size(); i++) {
Job j = activeJobs.get(i);
buf.append("<li>(").append(_t("started {0} ago", DataHelper.formatDuration2(now - j.getTiming().getStartAfter()))).append("): ");
buf.append(j.toString()).append("</li>\n");
}
buf.append("</ol>\n");
buf.append("<h3 id=\"finishedjobs\">").append(_t("Just finished jobs")).append(": ").append(justFinishedJobs.size()).append("</h3><ol>");
for (int i = 0; i < justFinishedJobs.size(); i++) {
Job j = justFinishedJobs.get(i);
buf.append("<li>(").append(_t("finished {0} ago", DataHelper.formatDuration2(now - j.getTiming().getActualEnd()))).append("): ");
buf.append(j.toString()).append("</li>\n");
}
buf.append("</ol>\n");
buf.append("<h3 id=\"readyjobs\">").append(_t("Ready/waiting jobs")).append(": ").append(readyJobs.size()).append("</h3><ol>");
ObjectCounter<String> counter = new ObjectCounter<String>();
for (int i = 0; i < readyJobs.size(); i++) {
Job j = readyJobs.get(i);
counter.increment(j.getName());
if (i >= MAX_JOBS)
continue;
buf.append("<li>[waiting ");
buf.append(DataHelper.formatDuration2(now - j.getTiming().getStartAfter()));
buf.append("]: ");
buf.append(j.toString()).append("</li>\n");
}
buf.append("</ol>\n");
getJobCounts(buf, counter);
out.write(buf.toString());
buf.setLength(0);
buf.append("<h3 id=\"scheduledjobs\">").append(_t("Scheduled jobs")).append(": ").append(timedJobs.size()).append("</h3><ol>");
long prev = Long.MIN_VALUE;
counter.clear();
for (int i = 0; i < timedJobs.size(); i++) {
Job j = timedJobs.get(i);
counter.increment(j.getName());
if (i >= MAX_JOBS)
continue;
long time = j.getTiming().getStartAfter() - now;
// translators: {0} is a job name, {1} is a time, e.g. 6 min
buf.append("<li>").append(_t("{0} will start in {1}", j.getName(), DataHelper.formatDuration2(time)));
// debug, don't bother translating
if (time < 0)
buf.append(" <b>DELAYED</b>");
if (time < prev)
buf.append(" <b>** OUT OF ORDER **</b>");
prev = time;
buf.append("</li>\n");
}
buf.append("</ol></div>\n");
getJobCounts(buf, counter);
out.write(buf.toString());
buf.setLength(0);
buf.append("<h3 id=\"totaljobstats\">").append(_t("Total Job Statistics")).append("</h3>\n");
getJobStats(buf);
out.write(buf.toString());
}
use of net.i2p.router.Job in project i2p.i2p by i2p.
the class HandleFloodfillDatabaseStoreMessageJob method sendAck.
private void sendAck(Hash storedKey) {
DeliveryStatusMessage msg = new DeliveryStatusMessage(getContext());
msg.setMessageId(_message.getReplyToken());
// Randomize for a little protection against clock-skew fingerprinting.
// But the "arrival" isn't used for anything, right?
// TODO just set to 0?
// TODO we have no session to garlic wrap this with, needs new message
msg.setArrival(getContext().clock().now() - getContext().random().nextInt(3 * 1000));
// may be null
TunnelId replyTunnel = _message.getReplyTunnel();
// A store of our own RI, only if we are not FF
DatabaseStoreMessage msg2;
if ((getContext().netDb().floodfillEnabled() && !getContext().router().gracefulShutdownInProgress()) || storedKey.equals(getContext().routerHash())) {
// don't send our RI if the store was our RI (from PeerTestJob)
msg2 = null;
} else {
// we aren't ff, send a go-away message
msg2 = new DatabaseStoreMessage(getContext());
RouterInfo me = getContext().router().getRouterInfo();
msg2.setEntry(me);
if (_log.shouldWarn())
_log.warn("Got a store w/ reply token, but we aren't ff: from: " + _from + " fromHash: " + _fromHash + " msg: " + _message, new Exception());
}
Hash toPeer = _message.getReplyGateway();
boolean toUs = getContext().routerHash().equals(toPeer);
// else through an exploratory tunnel.
if (toUs && replyTunnel != null) {
// if we are the gateway, act as if we received it
TunnelGatewayMessage tgm = new TunnelGatewayMessage(getContext());
tgm.setMessage(msg);
tgm.setTunnelId(replyTunnel);
tgm.setMessageExpiration(msg.getMessageExpiration());
getContext().tunnelDispatcher().dispatch(tgm);
if (msg2 != null) {
TunnelGatewayMessage tgm2 = new TunnelGatewayMessage(getContext());
tgm2.setMessage(msg2);
tgm2.setTunnelId(replyTunnel);
tgm2.setMessageExpiration(msg.getMessageExpiration());
getContext().tunnelDispatcher().dispatch(tgm2);
}
} else if (toUs || getContext().commSystem().isEstablished(toPeer)) {
Job send = new SendMessageDirectJob(getContext(), msg, toPeer, REPLY_TIMEOUT, MESSAGE_PRIORITY);
send.runJob();
if (msg2 != null) {
Job send2 = new SendMessageDirectJob(getContext(), msg2, toPeer, REPLY_TIMEOUT, MESSAGE_PRIORITY);
send2.runJob();
}
} else {
// pick tunnel with endpoint closest to toPeer
TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundExploratoryTunnel(toPeer);
if (outTunnel == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("No outbound tunnel could be found");
return;
}
getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnel.getSendTunnelId(0), replyTunnel, toPeer);
if (msg2 != null)
getContext().tunnelDispatcher().dispatchOutbound(msg2, outTunnel.getSendTunnelId(0), replyTunnel, toPeer);
}
}
use of net.i2p.router.Job in project i2p.i2p by i2p.
the class IterativeSearchJob method success.
@Override
void success() {
// Sadly, we don't know for sure which one replied.
// If the reply is after expiration (which moves the hash from _unheardFrom to _failedPeers),
// we will credit the wrong one.
int tries;
Hash peer = null;
synchronized (this) {
if (_dead)
return;
_dead = true;
_success = true;
tries = _unheardFrom.size() + _failedPeers.size();
if (_unheardFrom.size() == 1) {
peer = _unheardFrom.iterator().next();
_unheardFrom.clear();
}
}
_facade.complete(_key);
if (peer != null) {
Long timeSent = _sentTime.get(peer);
if (timeSent != null)
getContext().profileManager().dbLookupSuccessful(peer, getContext().clock().now() - timeSent.longValue());
}
long time = System.currentTimeMillis() - _created;
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": ISJ for " + _key + " successful after " + time + ", peers queried: " + tries);
getContext().statManager().addRateData("netDb.successTime", time);
getContext().statManager().addRateData("netDb.successRetries", tries - 1);
for (Job j : _onFind) {
getContext().jobQueue().addJob(j);
}
_onFind.clear();
}
use of net.i2p.router.Job in project i2p.i2p by i2p.
the class IterativeSearchJob method failed.
/**
* Total failure
*/
@Override
void failed() {
synchronized (this) {
if (_dead)
return;
_dead = true;
}
_facade.complete(_key);
if (getContext().commSystem().getStatus() != Status.DISCONNECTED)
_facade.lookupFailed(_key);
getContext().messageRegistry().unregisterPending(_out);
int tries;
final List<Hash> unheard;
synchronized (this) {
tries = _unheardFrom.size() + _failedPeers.size();
unheard = new ArrayList<Hash>(_unheardFrom);
}
// blame the unheard-from (others already blamed in failed() above)
for (Hash h : unheard) {
getContext().profileManager().dbLookupFailed(h);
}
long time = System.currentTimeMillis() - _created;
if (_log.shouldLog(Log.INFO)) {
long timeRemaining = _expiration - getContext().clock().now();
_log.info(getJobId() + ": ISJ for " + _key + " failed with " + timeRemaining + " remaining after " + time + ", peers queried: " + tries);
}
if (tries > 0) {
// don't bias the stats with immediate fails
getContext().statManager().addRateData("netDb.failedTime", time);
getContext().statManager().addRateData("netDb.failedRetries", tries - 1);
}
for (Job j : _onFailed) {
getContext().jobQueue().addJob(j);
}
_onFailed.clear();
}
use of net.i2p.router.Job in project i2p.i2p by i2p.
the class FloodOnlySearchJob method success.
@Override
void success() {
synchronized (this) {
if (_dead)
return;
_dead = true;
super.success();
}
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Floodfill search for " + _key + " successful");
// Sadly, we don't know which of the two replied, unless the first one sent a DSRM
// before the second one sent the answer, which isn't that likely.
// Would be really nice to fix this, but it isn't clear how unless CONCURRENT_SEARCHES == 1.
// Maybe don't unregister the msg from the Registry for a while and see if we get a 2nd reply?
// Or delay the 2nd search for a few seconds?
// We'll have to rely primarily on other searches (ExploreJob which calls SearchJob,
// and FloodfillVerifyStoreJob) to record successful searches for now.
// StoreJob also calls dbStoreSent() which updates the lastHeardFrom timer - this also helps.
long time = System.currentTimeMillis() - _created;
synchronized (_unheardFrom) {
if (_unheardFrom.size() == 1) {
Hash peer = _unheardFrom.iterator().next();
getContext().profileManager().dbLookupSuccessful(peer, time);
}
}
_facade.complete(_key);
getContext().statManager().addRateData("netDb.successTime", time);
for (Job j : _onFind) {
getContext().jobQueue().addJob(j);
}
}
Aggregations