2005-12-16 jrandom

* Refuse torrents with too many files (128), avoiding ulimit errors.
    * Remove an fd leak in I2PSnark
    * Further I2PSnark web UI cleanup
This commit is contained in:
jrandom
2005-12-16 08:24:21 +00:00
committed by zzz
parent 2a922098d6
commit 7726bd1a5c
8 changed files with 114 additions and 27 deletions

View File

@ -33,6 +33,7 @@ public class PeerCoordinator implements PeerListener
private final Log _log = new Log(PeerCoordinator.class);
final MetaInfo metainfo;
final Storage storage;
final Snark snark;
// package local for access by CheckDownLoadersTask
final static long CHECK_PERIOD = 20*1000; // 20 seconds
@ -70,12 +71,13 @@ public class PeerCoordinator implements PeerListener
public int trackerSeenPeers = 0;
public PeerCoordinator(byte[] id, MetaInfo metainfo, Storage storage,
CoordinatorListener listener)
CoordinatorListener listener, Snark torrent)
{
this.id = id;
this.metainfo = metainfo;
this.storage = storage;
this.listener = listener;
this.snark = torrent;
// Make a list of pieces
wantedPieces = new ArrayList();
@ -400,8 +402,9 @@ public class PeerCoordinator implements PeerListener
}
catch (IOException ioe)
{
Snark.fatal("Error reading storage", ioe);
return null; // Never reached.
snark.stopTorrent();
_log.error("Error reading the storage for " + metainfo.getName(), ioe);
throw new RuntimeException("B0rked");
}
}
@ -476,7 +479,9 @@ public class PeerCoordinator implements PeerListener
}
catch (IOException ioe)
{
Snark.fatal("Error writing storage", ioe);
snark.stopTorrent();
_log.error("Error writing storage for " + metainfo.getName(), ioe);
throw new RuntimeException("B0rked");
}
wantedPieces.remove(p);
}

View File

@ -333,7 +333,7 @@ public class Snark
}
debug(meta.toString(), INFO);
// When the metainfo torrent was created from an existing file/dir
// it already exists.
if (storage == null)
@ -346,12 +346,15 @@ public class Snark
}
catch (IOException ioe)
{
try { storage.close(); } catch (IOException ioee) {
ioee.printStackTrace();
}
fatal("Could not create storage", ioe);
}
}
activity = "Collecting pieces";
coordinator = new PeerCoordinator(id, meta, storage, clistener);
coordinator = new PeerCoordinator(id, meta, storage, clistener, this);
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
set.add(coordinator);
PeerAcceptor peeracceptor = new PeerAcceptor(set); //coordinator);
@ -374,7 +377,7 @@ public class Snark
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
set.remove(coordinator);
PeerCoordinator newCoord = new PeerCoordinator(coordinator.getID(), coordinator.getMetaInfo(),
coordinator.getStorage(), coordinator.getListener());
coordinator.getStorage(), coordinator.getListener(), this);
set.add(newCoord);
coordinator = newCoord;
coordinatorChanged = true;
@ -569,7 +572,7 @@ public class Snark
/**
* Aborts program abnormally.
*/
public static void fatal(String s)
public void fatal(String s)
{
fatal(s, null);
}
@ -577,12 +580,13 @@ public class Snark
/**
* Aborts program abnormally.
*/
public static void fatal(String s, Throwable t)
public void fatal(String s, Throwable t)
{
I2PSnarkUtil.instance().debug(s, ERROR, t);
//System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
//if (debug >= INFO && t != null)
// t.printStackTrace();
stopTorrent();
throw new RuntimeException("die bart die");
}

View File

@ -42,7 +42,7 @@ public class SnarkManager implements Snark.CompleteListener {
monitor.start();
}
private static final int MAX_MESSAGES = 10;
private static final int MAX_MESSAGES = 5;
public void addMessage(String message) {
synchronized (_messages) {
_messages.add(message);
@ -243,6 +243,9 @@ public class SnarkManager implements Snark.CompleteListener {
public Properties getConfig() { return _config; }
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
private static final int MAX_FILES_PER_TORRENT = 128;
/** set of filenames that we are dealing with */
public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
/**
@ -250,6 +253,14 @@ public class SnarkManager implements Snark.CompleteListener {
*/
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
public void addTorrent(String filename) {
if (!I2PSnarkUtil.instance().connected()) {
addMessage("Connecting to I2P");
boolean ok = I2PSnarkUtil.instance().connect();
if (!ok) {
addMessage("Error connecting to I2P - check your I2CP settings");
return;
}
}
File sfile = new File(filename);
try {
filename = sfile.getCanonicalPath();
@ -263,9 +274,31 @@ public class SnarkManager implements Snark.CompleteListener {
synchronized (_snarks) {
torrent = (Snark)_snarks.get(filename);
if (torrent == null) {
torrent = new Snark(filename, null, -1, null, null, false, dataDir.getPath());
torrent.completeListener = this;
_snarks.put(filename, torrent);
FileInputStream fis = null;
try {
fis = new FileInputStream(sfile);
MetaInfo info = new MetaInfo(fis);
fis.close();
fis = null;
List files = info.getFiles();
if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) {
sfile.delete();
addMessage("Too many files in " + sfile.getName() + " (" + files.size() + "), deleting it");
return;
} else {
torrent = new Snark(filename, null, -1, null, null, false, dataDir.getPath());
torrent.completeListener = this;
_snarks.put(filename, torrent);
}
} catch (IOException ioe) {
addMessage("Torrent in " + sfile.getName() + " is invalid: " + ioe.getMessage());
if (sfile.exists())
sfile.delete();
return;
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
} else {
return;
}
@ -330,6 +363,12 @@ public class SnarkManager implements Snark.CompleteListener {
private class DirMonitor implements Runnable {
public void run() {
try { Thread.sleep(60*1000*getStartupDelayMinutes()); } catch (InterruptedException ie) {}
// the first message was a "We are starting up in 1m"
synchronized (_messages) {
if (_messages.size() == 1)
_messages.remove(0);
}
while (true) {
File dir = getDataDir();
_log.debug("Directory Monitor loop over " + dir.getAbsolutePath());

View File

@ -72,7 +72,8 @@ public class SnarkShutdown extends Thread
}
catch(IOException ioe)
{
Snark.fatal("Couldn't properly close storage", ioe);
I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
throw new RuntimeException("b0rking");
}
}

View File

@ -404,10 +404,15 @@ public class Storage
{
for (int i = 0; i < rafs.length; i++)
{
synchronized(rafs[i])
{
rafs[i].close();
}
try {
synchronized(rafs[i])
{
rafs[i].close();
}
} catch (IOException ioe) {
I2PSnarkUtil.instance().debug("Error closing " + rafs[i], Snark.ERROR, ioe);
// gobble gobble
}
}
}

View File

@ -254,8 +254,9 @@ public class TrackerClient extends Thread
throw new IOException("Error fetching " + s);
}
InputStream in = null;
try {
InputStream in = new FileInputStream(fetched);
in = new FileInputStream(fetched);
TrackerInfo info = new TrackerInfo(in, coordinator.getID(),
coordinator.getMetaInfo());
@ -270,6 +271,7 @@ public class TrackerClient extends Thread
interval = info.getInterval() * 1000;
return info;
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
fetched.delete();
}
}

View File

@ -53,14 +53,18 @@ public class I2PSnarkServlet extends HttpServlet {
// we want it to go to the base URI so we don't refresh with some funky action= value
out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + "\">\n");
out.write(HEADER);
out.write("<a href=\"" + req.getRequestURI() + "\">Refresh</a>\n");
out.write("<textarea class=\"snarkMessages\" rows=\"2\" cols=\"100\" wrap=\"off\" >");
out.write("<table border=\"0\" width=\"100%\">\n");
out.write("<tr><td width=\"5%\" class=\"snarkTitle\" valign=\"top\" align=\"left\">");
out.write("I2PSnark<br />\n");
out.write("<a href=\"" + req.getRequestURI() + "\" class=\"snarkRefresh\">Refresh</a>\n");
out.write("</td><td width=\"95%\" class=\"snarkMessages\" valign=\"top\" align=\"left\"><pre>");
List msgs = _manager.getMessages();
for (int i = msgs.size()-1; i >= 0; i--) {
String msg = (String)msgs.get(i);
out.write(msg + "\n");
}
out.write("</textarea>\n");
out.write("</pre></td></tr></table>\n");
out.write(TABLE_HEADER);
@ -302,6 +306,7 @@ public class I2PSnarkServlet extends HttpServlet {
boolean isRunning = !snark.stopped;
boolean isValid = snark.meta != null;
boolean singleFile = snark.meta.getFiles() == null;
String err = snark.coordinator.trackerProblems;
int curPeers = snark.coordinator.getPeerCount();
@ -330,7 +335,15 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<td valign=\"top\" align=\"left\" class=\"snarkTorrentStatus " + rowClass + "\">");
out.write(statusString + "</td>\n\t");
out.write("<td valign=\"top\" align=\"left\" class=\"snarkTorrentName " + rowClass + "\">");
out.write(filename + "</td>\n\t");
if (remaining == 0)
out.write("<a href=\"file:///" + _manager.getDataDir().getAbsolutePath() + File.separatorChar + snark.meta.getName()
+ "\" title=\"Download the completed file\">");
out.write(filename);
if (remaining == 0)
out.write("</a>");
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"left\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
if (remaining > 0) {
out.write(formatSize(total-remaining) + "/" + formatSize(total)); // 18MB/3GB
@ -380,7 +393,8 @@ public class I2PSnarkServlet extends HttpServlet {
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br />\n");
out.write("<input type=\"submit\" value=\"Add torrent\" name=\"action\" /><br />\n");
out.write("Alternately, you can copy .torrent files to " + _manager.getDataDir().getAbsolutePath() + "<br />\n");
out.write("<span class=\"snarkAddInfo\">Alternately, you can copy .torrent files to " + _manager.getDataDir().getAbsolutePath() + "<br />\n");
out.write("Removing that .torrent file will cause the torrent to stop.<br /></span>\n");
out.write("</form>\n</span>\n");
}
@ -466,12 +480,22 @@ public class I2PSnarkServlet extends HttpServlet {
" font-size: 16pt;\n" +
" font-weight: bold;\n" +
"}\n" +
".snarkRefresh {\n" +
" font-size: 10pt;\n" +
"}\n" +
".snarkMessages {\n" +
" border: none;\n" +
" background-color: #CECFC6;\n" +
" font-family: monospace;\n" +
" font-size: 10pt;\n" +
" font-weight: 100;\n" +
" width: 100%;\n" +
" text-align: left;\n" +
" margin: 0px 0px 0px 0px;\n" +
" border: 0px;\n" +
" padding: 5px;\n" +
" border-width: 0px;\n" +
" border-spacing: 0px;\n" +
"}\n" +
"table {\n" +
" margin: 0px 0px 0px 0px;\n" +
@ -495,14 +519,16 @@ public class I2PSnarkServlet extends HttpServlet {
" font-family: monospace;\n" +
" background-color: #ADAE9;\n" +
"}\n" +
".snarkAddInfo {\n" +
" font-size: 10pt;\n" +
"}\n" +
".snarkConfigTitle {\n" +
" font-size: 16pt;\n" +
" font-weight: bold;\n" +
"}\n" +
"</style>\n" +
"</head>\n" +
"<body>\n" +
"<p class=\"snarkTitle\">I2PSnark&nbsp;</p>\n";
"<body>\n";
private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\">\n" +

View File

@ -1,4 +1,9 @@
$Id: history.txt,v 1.356 2005/12/15 03:58:31 jrandom Exp $
$Id: history.txt,v 1.357 2005/12/15 22:00:48 jrandom Exp $
2005-12-16 jrandom
* Refuse torrents with too many files (128), avoiding ulimit errors.
* Remove an fd leak in I2PSnark
* Further I2PSnark web UI cleanup
2005-12-15 jrandom
* Added a first pass to the I2PSnark web UI (see /i2psnark/)