lots of bitchin' oOo patches (woot, thanks oOo!), plus some cleanup

* apply oOo's patch for beautifying the new console w/ links to a shitlisted peer's netDb entry
* apply oOo's patch to clean up the peer shitlist count more aggressively
* apply oOo's patch to allow removing lines via /configadvanced.jsp
* apply oOo's patch to clean up the memory usage display
* apply oOo's patch to include log messages on /logs.jsp most recent first, rather than last
* get rid of the netDb key shitlist (its a bad idea, better solution coming soon)
This commit is contained in:
jrandom
2004-08-16 20:27:06 +00:00
committed by zzz
parent bf3ee5c158
commit e102bf9eed
8 changed files with 58 additions and 107 deletions

View File

@ -4,6 +4,8 @@ import java.io.ByteArrayInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Iterator;
/**
* Handler to deal with form submissions from the advanced config form and act
@ -41,6 +43,7 @@ public class ConfigAdvancedHandler extends FormHandler {
*
*/
private void saveChanges() {
HashSet unsetKeys = new HashSet(_context.router().getConfigMap().keySet());
if (_config != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(_config.getBytes())));
String line = null;
@ -52,12 +55,19 @@ public class ConfigAdvancedHandler extends FormHandler {
String key = line.substring(0, eq).trim();
String val = line.substring(eq + 1).trim();
_context.router().setConfigSetting(key, val);
unsetKeys.remove(key);
}
} catch (IOException ioe) {
addFormError("Error updating the configuration (IOERROR) - please see the error logs");
return;
}
Iterator cleaner = unsetKeys.iterator();
while (cleaner.hasNext()) {
String unsetKey = (String)cleaner.next();
_context.router().removeConfigSetting(unsetKey);
}
boolean saved = _context.router().saveConfig();
if (saved)
addFormNotice("Configuration saved successfully");

View File

@ -29,8 +29,8 @@ public class LogsHelper {
StringBuffer buf = new StringBuffer(16*1024);
buf.append("<h2>Most recent console messages:</h2><ul>");
buf.append("<code>\n");
for (int i = 0; i < msgs.size(); i++) {
String msg = (String)msgs.get(i);
for (int i = msgs.size(); i > 0; i--) {
String msg = (String)msgs.get(i - 1);
buf.append("<li>");
buf.append(msg);
buf.append("</li>\n");

View File

@ -71,9 +71,10 @@ public class SummaryHelper {
*
*/
public String getMemory() {
DecimalFormat integerFormatter = new DecimalFormat("###,###,##0");
long used = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024;
long usedPc = 100 - ((Runtime.getRuntime().freeMemory() * 100) / Runtime.getRuntime().totalMemory());
return used + "KB (" + usedPc + "%)";
return integerFormatter.format(used) + "KB (" + usedPc + "%)";
}
/**

View File

@ -23,7 +23,7 @@
<i><jsp:getProperty name="formhandler" property="notices" /></i>
<form action="configadvanced.jsp" method="POST">
<textarea rows="20" cols="80" name="config"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br />
<textarea rows="20" cols="100" name="config"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br />
<input type="submit" name="shouldsave" value="Apply" /> <input type="reset" value="Cancel" /> <br />
<b>Force restart:</b> <input type="checkbox" name="restart" value="force" /> <i>(specify this
if the changes made above require the router to reset itself - e.g. you are updating TCP ports

View File

@ -123,6 +123,7 @@ public class Router {
public String getConfigSetting(String name) { return _config.getProperty(name); }
public void setConfigSetting(String name, String value) { _config.setProperty(name, value); }
public void removeConfigSetting(String name) { _config.remove(name); }
public Set getConfigSettings() { return new HashSet(_config.keySet()); }
public Properties getConfigMap() { return _config; }

View File

@ -40,6 +40,7 @@ public class Shitlist {
}
public int getRouterCount() {
purge();
synchronized (_shitlist) {
return _shitlist.size();
}
@ -98,16 +99,17 @@ public class Shitlist {
}
}
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(1024);
buf.append("<h2>Shitlist</h2>");
/**
* We already unshitlist on isShitlisted, but this purge
* lets us get the correct value when rendering the HTML or
* getting the shitlist count. wheee
*
*/
private void purge() {
Map shitlist = null;
Map causes = null;
synchronized (_shitlist) {
shitlist = new HashMap(_shitlist);
causes = new HashMap(_shitlistCause);
}
buf.append("<ul>");
long limit = _context.clock().now() - SHITLIST_DURATION_MS;
@ -116,17 +118,39 @@ public class Shitlist {
Date shitDate = (Date)shitlist.get(key);
if (shitDate.getTime() < limit) {
unshitlistRouter(key);
} else {
buf.append("<li><b>").append(key.toBase64()).append("</b> was shitlisted on ");
buf.append(shitDate);
String cause = (String)causes.get(key);
if (cause != null) {
buf.append("<br />\n");
buf.append(cause);
}
buf.append("</li>\n");
}
}
}
public void renderStatusHTML(OutputStream out) throws IOException {
StringBuffer buf = new StringBuffer(1024);
buf.append("<h2>Shitlist</h2>");
Map shitlist = null;
Map causes = null;
purge();
synchronized (_shitlist) {
shitlist = new HashMap(_shitlist);
causes = new HashMap(_shitlistCause);
}
buf.append("<ul>");
for (Iterator iter = shitlist.keySet().iterator(); iter.hasNext(); ) {
Hash key = (Hash)iter.next();
Date shitDate = (Date)shitlist.get(key);
buf.append("<li><b>").append(key.toBase64()).append("</b>");
buf.append(" <a href=\"netdb.jsp#").append(key.toBase64().substring(0, 6)).append("\">(?)</a>");
buf.append(" was shitlisted on ");
buf.append(shitDate);
String cause = (String)causes.get(key);
if (cause != null) {
buf.append("<br />\n");
buf.append(cause);
}
buf.append("</li>\n");
}
buf.append("</ul>\n");
out.write(buf.toString().getBytes());
}

View File

@ -73,17 +73,6 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
*/
private Set _publishingLeaseSets;
/**
* List of keys that we've recently done full searches on and failed.
*
*/
private Set _badKeys;
/**
* Mapping when (Long) to Hash for keys that are in the _badKeys list.
*
*/
private Map _badKeyDates;
/**
* for the 10 minutes after startup, don't fail db entries so that if we were
* offline for a while, we'll have a chance of finding some live peers with the
@ -107,78 +96,6 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
_peerSelector = new PeerSelector(_context);
_publishingLeaseSets = new HashSet(8);
_lastExploreNew = 0;
_badKeys = new HashSet();
_badKeyDates = new TreeMap();
}
/**
* if we do a full search for a key and still fail, don't try again
* for another 5 minutes
*/
private static final long SHITLIST_TIME = 5*60*1000;
/**
* Are we currently avoiding this key?
*
*/
boolean isShitlisted(Hash key) {
synchronized (_badKeys) {
locked_cleanupShitlist();
boolean isShitlisted = _badKeys.contains(key);
if (!isShitlisted) return false;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Key " + key.toBase64() + " is shitlisted");
return true;
}
}
/**
* For some reason, we don't want to try any remote lookups for this key
* anytime soon - for instance, we may have just failed to find it after a
* full netDb search.
*
*/
void shitlist(Hash key) {
synchronized (_badKeys) {
locked_cleanupShitlist();
boolean wasNew = _badKeys.add(key);
if (wasNew) {
long when = _context.clock().now();
while (_badKeyDates.containsKey(new Long(when)))
when++;
_badKeyDates.put(new Long(when), key);
_log.info("Shitlist " + key.toBase64() + " - new shitlist");
} else {
_log.info("Shitlist " + key.toBase64() + " - already shitlisted");
}
}
}
private void locked_cleanupShitlist() {
List old = null;
long keepAfter = _context.clock().now() - SHITLIST_TIME;
for (Iterator iter = _badKeyDates.keySet().iterator(); iter.hasNext(); ) {
Long when = (Long)iter.next();
Hash key = (Hash)_badKeyDates.get(when);
if (when.longValue() < keepAfter) {
if (old == null)
old = new ArrayList(4);
old.add(when);
} else {
// ordered
break;
}
}
if (old != null) {
for (int i = 0; i < old.size(); i++) {
Long when = (Long)old.get(i);
Hash key = (Hash)_badKeyDates.remove(when);
_badKeys.remove(key);
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Cleaning up shitlist: " + _badKeys.size() + " remain after removing "
+ (old != null ? old.size() : 0));
}
KBucketSet getKBuckets() { return _kb; }
@ -828,10 +745,11 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
}
private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) {
String hash = info.getIdentity().getHash().toBase64();
if (isUs) {
buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />");
buf.append("<b>Our info: </b><br />\n");
} else {
String hash = info.getIdentity().getHash().toBase64();
buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />");
buf.append("<b>Peer info for:</b> ").append(hash).append("<br />\n");
}

View File

@ -531,9 +531,6 @@ class SearchJob extends JobImpl {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": State of failed search: " + _state);
// ok, we totally failed, so don't try again for that key too quickly
_facade.shitlist(_state.getTarget());
if (_keepStats) {
long time = getContext().clock().now() - _state.getWhenStarted();
getContext().statManager().addRateData("netDb.failedTime", time, 0);