i2psnark: Add recheck/start/stop buttons to details page (ticket #372)

remove dup CSS item
This commit is contained in:
zzz
2015-09-19 17:05:09 +00:00
parent 462c882f4e
commit 287f94ad19
8 changed files with 176 additions and 29 deletions

View File

@ -1264,7 +1264,8 @@ public class Snark
public void setWantedPieces(Storage storage)
{
coordinator.setWantedPieces();
if (coordinator != null)
coordinator.setWantedPieces();
}
///////////// End StorageListener methods

View File

@ -8,6 +8,7 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -2364,28 +2365,36 @@ public class SnarkManager implements CompleteListener {
public void startTorrent(byte[] infoHash) {
for (Snark snark : _snarks.values()) {
if (DataHelper.eq(infoHash, snark.getInfoHash())) {
if (snark.isStarting() || !snark.isStopped()) {
addMessage("Torrent already started");
return;
}
boolean connected = _util.connected();
if ((!connected) && !_util.isConnecting())
addMessage(_("Opening the I2P tunnel"));
addMessage(_("Starting up torrent {0}", snark.getBaseName()));
if (connected) {
snark.startTorrent();
} else {
// mark it for the UI
snark.setStarting();
(new I2PAppThread(new ThreadedStarter(snark), "TorrentStarter", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
startTorrent(snark);
return;
}
}
addMessage("Torrent not found?");
}
/**
* If not connected, thread it, otherwise inline
* @since 0.9.23
*/
public void startTorrent(Snark snark) {
if (snark.isStarting() || !snark.isStopped()) {
addMessage("Torrent already started");
return;
}
boolean connected = _util.connected();
if ((!connected) && !_util.isConnecting())
addMessage(_("Opening the I2P tunnel"));
addMessage(_("Starting up torrent {0}", snark.getBaseName()));
if (connected) {
snark.startTorrent();
} else {
// mark it for the UI
snark.setStarting();
(new I2PAppThread(new ThreadedStarter(snark), "TorrentStarter", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
}
/**
* If not connected, thread it, otherwise inline
* @since 0.9.1
@ -2498,6 +2507,55 @@ public class SnarkManager implements CompleteListener {
}
}
}
/**
* Threaded. Torrent must be stopped.
* @since 0.9.23
*/
public void recheckTorrent(Snark snark) {
if (snark.isStarting() || !snark.isStopped()) {
addMessage("Cannot check " + snark.getBaseName() + ", torrent already started");
return;
}
Storage storage = snark.getStorage();
if (storage == null) {
addMessage("Cannot check " + snark.getBaseName() + ", no storage");
return;
}
(new I2PAppThread(new ThreadedRechecker(snark), "TorrentRechecker", true)).start();
try { Thread.sleep(200); } catch (InterruptedException ie) {}
}
/**
* @since 0.9.23
*/
private class ThreadedRechecker implements Runnable {
private final Snark snark;
/** must have non-null storage */
public ThreadedRechecker(Snark s) { snark = s; }
public void run() {
try {
if (_log.shouldWarn())
_log.warn("Starting recheck of " + snark.getBaseName());
boolean changed = snark.getStorage().recheck();
if (changed)
updateStatus(snark);
if (_log.shouldWarn())
_log.warn("Finished recheck of " + snark.getBaseName() + " changed? " + changed);
if (changed) {
int pieces = snark.getPieces();
double completion = (pieces - snark.getNeeded()) / (double) pieces;
String complete = (new DecimalFormat("0.00%")).format(completion);
addMessage(_("Finished recheck of torrent {0}, now {1} complete", snark.getBaseName(), complete));
} else {
addMessage(_("Finished recheck of torrent {0}, unchanged", snark.getBaseName()));
}
} catch (Exception e) {
_log.error("Error rechecking " + snark.getBaseName(), e);
addMessage(_("Error checking the torrent {0}", snark.getBaseName()) + ": " + e);
}
}
}
/**
* ignore case, current locale

View File

@ -533,6 +533,9 @@ public class Storage implements Closeable
/**
* Creates (and/or checks) all files from the metainfo file list.
* Only call this once, and only after the constructor with the metainfo.
* Use recheck() to check again later.
*
* @throws IllegalStateException if called more than once
*/
public void check() throws IOException
{
@ -543,6 +546,9 @@ public class Storage implements Closeable
* Creates (and/or checks) all files from the metainfo file list.
* Use a saved bitfield and timestamp from a config file.
* Only call this once, and only after the constructor with the metainfo.
* Use recheck() to check again later.
*
* @throws IllegalStateException if called more than once
*/
public void check(long savedTime, BitField savedBitField) throws IOException
{
@ -821,6 +827,24 @@ public class Storage implements Closeable
return rv;
}
/**
* Blocking. Holds lock.
* Recommend running only when stopped.
* Caller should thread.
* Calls listener.setWantedPieces() on completion if anything changed.
*
* @return true if anything changed, false otherwise
* @since 0.9.23
*/
public boolean recheck() throws IOException {
int previousNeeded = needed;
checkCreateFiles(true);
boolean changed = previousNeeded != needed;
if (listener != null && changed)
listener.setWantedPieces(this);
return changed;
}
/**
* This is called at the beginning, and at presumed completion,
* so we have to be careful about locking.

View File

@ -2613,10 +2613,21 @@ public class I2PSnarkServlet extends BasicServlet {
String[] val = postParams.get("nonce");
if (val != null) {
String nonce = val[0];
if (String.valueOf(_nonce).equals(nonce))
savePriorities(snark, postParams);
else
if (String.valueOf(_nonce).equals(nonce)) {
if (postParams.get("savepri") != null) {
savePriorities(snark, postParams);
} else if (postParams.get("stop") != null) {
_manager.stopTorrent(snark, false);
} else if (postParams.get("start") != null) {
_manager.startTorrent(snark);
} else if (postParams.get("recheck") != null) {
_manager.recheckTorrent(snark);
} else {
_manager.addMessage("Unknown command");
}
} else {
_manager.addMessage("Please retry form submission (bad nonce)");
}
}
return null;
}
@ -2639,6 +2650,7 @@ public class I2PSnarkServlet extends BasicServlet {
r = new File("");
}
boolean showStopStart = snark != null;
boolean showPriority = snark != null && snark.getStorage() != null && !snark.getStorage().complete() &&
r.isDirectory();
@ -2668,7 +2680,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (parent) // always true
buf.append("<div class=\"page\"><div class=\"mainsection\">");
if (showPriority) {
// for stop/start/check
if (showStopStart || showPriority) {
buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n");
buf.append("<input type=\"hidden\" name=\"nonce\" value=\"").append(_nonce).append("\" >\n");
if (sortParam != null) {
@ -2905,7 +2918,36 @@ public class I2PSnarkServlet extends BasicServlet {
.append(":</b> ")
.append(formatSize(snark.getPieceLength(0)))
.append("</td></tr>\n");
// buttons
if (showStopStart) {
buf.append("<tr><td>");
toThemeImg(buf, "file");
if (snark.isChecking()) {
buf.append("&nbsp;<b>").append(_("Checking")).append("&hellip;</b>&nbsp;&nbsp;&nbsp;")
.append("<a href=\"").append(base).append("\">")
.append(_("Refresh page for results")).append("</a>");
} else if (snark.isStarting()) {
buf.append("&nbsp;<b>").append(_("Starting")).append("&hellip;</b>");
} else if (snark.isAllocating()) {
buf.append("&nbsp;<b>").append(_("Allocating")).append("&hellip;</b>");
} else {
boolean isRunning = !snark.isStopped();
buf.append(" <input type=\"submit\" value=\"");
if (isRunning)
buf.append(_("Stop")).append("\" name=\"stop\" class=\"stoptorrent\">\n");
else
buf.append(_("Start")).append("\" name=\"start\" class=\"starttorrent\">\n");
buf.append("&nbsp;&nbsp;&nbsp;<input type=\"submit\" name=\"recheck\" value=\"").append(_("Force Recheck"));
if (isRunning)
buf.append("\" class=\"disabled\" disabled=\"disabled\">\n");
else
buf.append("\" class=\"reload\">\n");
}
buf.append("</td></tr>\n");
}
} else {
// snark == null
// shouldn't happen
buf.append("<tr><th>Not found<br>resource=\"").append(r.toString())
.append("\"<br>base=\"").append(base)
@ -3158,7 +3200,8 @@ public class I2PSnarkServlet extends BasicServlet {
"</th></tr></thead>\n");
}
buf.append("</table>\n");
if (showPriority)
// for stop/start/check
if (showStopStart || showPriority)
buf.append("</form>");
buf.append("</div></div></BODY></HTML>\n");

View File

@ -1,3 +1,6 @@
2015-09-19 zzz
* i2psnark: Add recheck/start/stop buttons to details page (ticket #372)
2015-09-18 zzz
* EepGet:
- Send Accept-Encoding: gzip even when proxied

View File

@ -656,12 +656,6 @@ input.add {
min-height: 22px;
}
input.create {
background: #989 url('images/create.png') no-repeat 2px center;
padding: 2px 3px 2px 20px !important;
min-height: 22px;
}
input.cancel {
background: #989 url('../../console/images/cancel.png') no-repeat 2px center;
padding: 2px 3px 2px 20px !important;
@ -686,6 +680,18 @@ input.reload {
min-height: 22px;
}
input.starttorrent {
background: #989 url('images/start.png') no-repeat 2px center;
padding: 2px 3px 2px 20px !important;
min-height: 22px;
}
input.stoptorrent {
background: #989 url('images/stop.png') no-repeat 2px center;
padding: 2px 3px 2px 20px !important;
min-height: 22px;
}
select {
background: #333;
background: url('/themes/snark/ubergine/images/graytile.png') !important;

View File

@ -694,6 +694,18 @@ input.reload {
min-height: 22px;
}
input.starttorrent {
background: #f3efc7 url('images/start.png') no-repeat 2px center;
padding: 2px 3px 2px 20px !important;
min-height: 22px;
}
input.stoptorrent {
background: #f3efc7 url('images/stop.png') no-repeat 2px center;
padding: 2px 3px 2px 20px !important;
min-height: 22px;
}
select {
background: #fff;
/* background: url('/themes/snark/ubergine/images/graytile.png') !important;*/

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 6;
public final static long BUILD = 7;
/** for example "-test" */
public final static String EXTRA = "";