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.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; 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 * 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() { private void saveChanges() {
HashSet unsetKeys = new HashSet(_context.router().getConfigMap().keySet());
if (_config != null) { if (_config != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(_config.getBytes()))); BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(_config.getBytes())));
String line = null; String line = null;
@ -52,12 +55,19 @@ public class ConfigAdvancedHandler extends FormHandler {
String key = line.substring(0, eq).trim(); String key = line.substring(0, eq).trim();
String val = line.substring(eq + 1).trim(); String val = line.substring(eq + 1).trim();
_context.router().setConfigSetting(key, val); _context.router().setConfigSetting(key, val);
unsetKeys.remove(key);
} }
} catch (IOException ioe) { } catch (IOException ioe) {
addFormError("Error updating the configuration (IOERROR) - please see the error logs"); addFormError("Error updating the configuration (IOERROR) - please see the error logs");
return; return;
} }
Iterator cleaner = unsetKeys.iterator();
while (cleaner.hasNext()) {
String unsetKey = (String)cleaner.next();
_context.router().removeConfigSetting(unsetKey);
}
boolean saved = _context.router().saveConfig(); boolean saved = _context.router().saveConfig();
if (saved) if (saved)
addFormNotice("Configuration saved successfully"); addFormNotice("Configuration saved successfully");

View File

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

View File

@ -71,9 +71,10 @@ public class SummaryHelper {
* *
*/ */
public String getMemory() { public String getMemory() {
DecimalFormat integerFormatter = new DecimalFormat("###,###,##0");
long used = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024; long used = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024;
long usedPc = 100 - ((Runtime.getRuntime().freeMemory() * 100) / Runtime.getRuntime().totalMemory()); 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> <i><jsp:getProperty name="formhandler" property="notices" /></i>
<form action="configadvanced.jsp" method="POST"> <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 /> <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 <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 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 String getConfigSetting(String name) { return _config.getProperty(name); }
public void setConfigSetting(String name, String value) { _config.setProperty(name, value); } 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 Set getConfigSettings() { return new HashSet(_config.keySet()); }
public Properties getConfigMap() { return _config; } public Properties getConfigMap() { return _config; }

View File

@ -40,6 +40,7 @@ public class Shitlist {
} }
public int getRouterCount() { public int getRouterCount() {
purge();
synchronized (_shitlist) { synchronized (_shitlist) {
return _shitlist.size(); return _shitlist.size();
} }
@ -98,16 +99,17 @@ public class Shitlist {
} }
} }
public void renderStatusHTML(OutputStream out) throws IOException { /**
StringBuffer buf = new StringBuffer(1024); * We already unshitlist on isShitlisted, but this purge
buf.append("<h2>Shitlist</h2>"); * lets us get the correct value when rendering the HTML or
* getting the shitlist count. wheee
*
*/
private void purge() {
Map shitlist = null; Map shitlist = null;
Map causes = null;
synchronized (_shitlist) { synchronized (_shitlist) {
shitlist = new HashMap(_shitlist); shitlist = new HashMap(_shitlist);
causes = new HashMap(_shitlistCause);
} }
buf.append("<ul>");
long limit = _context.clock().now() - SHITLIST_DURATION_MS; long limit = _context.clock().now() - SHITLIST_DURATION_MS;
@ -116,8 +118,31 @@ public class Shitlist {
Date shitDate = (Date)shitlist.get(key); Date shitDate = (Date)shitlist.get(key);
if (shitDate.getTime() < limit) { if (shitDate.getTime() < limit) {
unshitlistRouter(key); unshitlistRouter(key);
} else { }
buf.append("<li><b>").append(key.toBase64()).append("</b> was shitlisted on "); }
}
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); buf.append(shitDate);
String cause = (String)causes.get(key); String cause = (String)causes.get(key);
if (cause != null) { if (cause != null) {
@ -126,7 +151,6 @@ public class Shitlist {
} }
buf.append("</li>\n"); buf.append("</li>\n");
} }
}
buf.append("</ul>\n"); buf.append("</ul>\n");
out.write(buf.toString().getBytes()); out.write(buf.toString().getBytes());
} }

View File

@ -73,17 +73,6 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
*/ */
private Set _publishingLeaseSets; 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 * 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 * 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); _peerSelector = new PeerSelector(_context);
_publishingLeaseSets = new HashSet(8); _publishingLeaseSets = new HashSet(8);
_lastExploreNew = 0; _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; } KBucketSet getKBuckets() { return _kb; }
@ -828,10 +745,11 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
} }
private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) { private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) {
String hash = info.getIdentity().getHash().toBase64();
if (isUs) { if (isUs) {
buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />");
buf.append("<b>Our info: </b><br />\n"); buf.append("<b>Our info: </b><br />\n");
} else { } else {
String hash = info.getIdentity().getHash().toBase64();
buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />"); buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />");
buf.append("<b>Peer info for:</b> ").append(hash).append("<br />\n"); 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)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": State of failed search: " + _state); _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) { if (_keepStats) {
long time = getContext().clock().now() - _state.getWhenStarted(); long time = getContext().clock().now() - _state.getWhenStarted();
getContext().statManager().addRateData("netDb.failedTime", time, 0); getContext().statManager().addRateData("netDb.failedTime", time, 0);