forked from I2P_Developers/i2p.i2p
i2psnark:
- Refactor file deletion in prep for better file name handling (ticket #571) - Don't use canonical files in directory listings, for speed and to avoid file comparison problems (tickets #1079, #1148) - Set base file/dir in Storage constructor, make final, in prep for arbitrary locations (ticket #1028)
This commit is contained in:
@@ -223,7 +223,7 @@ public class Snark
|
|||||||
private PeerCoordinator coordinator;
|
private PeerCoordinator coordinator;
|
||||||
private ConnectionAcceptor acceptor;
|
private ConnectionAcceptor acceptor;
|
||||||
private TrackerClient trackerclient;
|
private TrackerClient trackerclient;
|
||||||
private String rootDataDir = ".";
|
private final File rootDataDir;
|
||||||
private final CompleteListener completeListener;
|
private final CompleteListener completeListener;
|
||||||
private volatile boolean stopped;
|
private volatile boolean stopped;
|
||||||
private volatile boolean starting;
|
private volatile boolean starting;
|
||||||
@@ -291,7 +291,7 @@ public class Snark
|
|||||||
acceptor = connectionAcceptor;
|
acceptor = connectionAcceptor;
|
||||||
|
|
||||||
this.torrent = torrent;
|
this.torrent = torrent;
|
||||||
this.rootDataDir = rootDir;
|
this.rootDataDir = new File(rootDir);
|
||||||
|
|
||||||
stopped = true;
|
stopped = true;
|
||||||
activity = "Network setup";
|
activity = "Network setup";
|
||||||
@@ -395,13 +395,12 @@ public class Snark
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
activity = "Checking storage";
|
activity = "Checking storage";
|
||||||
storage = new Storage(_util, meta, slistener);
|
storage = new Storage(_util, rootDataDir, meta, slistener);
|
||||||
if (completeListener != null) {
|
if (completeListener != null) {
|
||||||
storage.check(rootDataDir,
|
storage.check(completeListener.getSavedTorrentTime(this),
|
||||||
completeListener.getSavedTorrentTime(this),
|
|
||||||
completeListener.getSavedTorrentBitField(this));
|
completeListener.getSavedTorrentBitField(this));
|
||||||
} else {
|
} else {
|
||||||
storage.check(rootDataDir);
|
storage.check();
|
||||||
}
|
}
|
||||||
// have to figure out when to reopen
|
// have to figure out when to reopen
|
||||||
// if (!start)
|
// if (!start)
|
||||||
@@ -453,7 +452,7 @@ public class Snark
|
|||||||
this.torrent = torrent;
|
this.torrent = torrent;
|
||||||
this.infoHash = ih;
|
this.infoHash = ih;
|
||||||
this.additionalTrackerURL = trackerURL;
|
this.additionalTrackerURL = trackerURL;
|
||||||
this.rootDataDir = rootDir;
|
this.rootDataDir = new File(rootDir);
|
||||||
stopped = true;
|
stopped = true;
|
||||||
id = generateID();
|
id = generateID();
|
||||||
|
|
||||||
@@ -548,7 +547,7 @@ public class Snark
|
|||||||
} else if (trackerclient.halted()) {
|
} else if (trackerclient.halted()) {
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
try {
|
try {
|
||||||
storage.reopen(rootDataDir);
|
storage.reopen();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
try { storage.close(); } catch (IOException ioee) {
|
try { storage.close(); } catch (IOException ioee) {
|
||||||
ioee.printStackTrace();
|
ioee.printStackTrace();
|
||||||
@@ -1104,8 +1103,8 @@ public class Snark
|
|||||||
public void gotMetaInfo(PeerCoordinator coordinator, MetaInfo metainfo) {
|
public void gotMetaInfo(PeerCoordinator coordinator, MetaInfo metainfo) {
|
||||||
try {
|
try {
|
||||||
// The following two may throw IOE...
|
// The following two may throw IOE...
|
||||||
storage = new Storage(_util, metainfo, this);
|
storage = new Storage(_util, rootDataDir, metainfo, this);
|
||||||
storage.check(rootDataDir);
|
storage.check();
|
||||||
// ... so don't set meta until here
|
// ... so don't set meta until here
|
||||||
meta = metainfo;
|
meta = metainfo;
|
||||||
if (completeListener != null) {
|
if (completeListener != null) {
|
||||||
|
@@ -32,7 +32,9 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.SortedSet;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@@ -52,6 +54,7 @@ public class Storage
|
|||||||
{
|
{
|
||||||
private final MetaInfo metainfo;
|
private final MetaInfo metainfo;
|
||||||
private final List<TorrentFile> _torrentFiles;
|
private final List<TorrentFile> _torrentFiles;
|
||||||
|
private final File _base;
|
||||||
private final StorageListener listener;
|
private final StorageListener listener;
|
||||||
private final I2PSnarkUtil _util;
|
private final I2PSnarkUtil _util;
|
||||||
private final Log _log;
|
private final Log _log;
|
||||||
@@ -88,10 +91,15 @@ public class Storage
|
|||||||
*
|
*
|
||||||
* Does not check storage. Caller MUST call check()
|
* Does not check storage. Caller MUST call check()
|
||||||
*/
|
*/
|
||||||
public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener)
|
public Storage(I2PSnarkUtil util, File rootDir, MetaInfo metainfo, StorageListener listener)
|
||||||
{
|
{
|
||||||
_util = util;
|
_util = util;
|
||||||
_log = util.getContext().logManager().getLog(Storage.class);
|
_log = util.getContext().logManager().getLog(Storage.class);
|
||||||
|
boolean areFilesPublic = _util.getFilesPublic();
|
||||||
|
if (areFilesPublic)
|
||||||
|
_base = new File(rootDir, filterName(metainfo.getName()));
|
||||||
|
else
|
||||||
|
_base = new SecureFile(rootDir, filterName(metainfo.getName()));
|
||||||
this.metainfo = metainfo;
|
this.metainfo = metainfo;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
needed = metainfo.getPieces();
|
needed = metainfo.getPieces();
|
||||||
@@ -121,6 +129,7 @@ public class Storage
|
|||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
_util = util;
|
_util = util;
|
||||||
|
_base = baseFile;
|
||||||
_log = util.getContext().logManager().getLog(Storage.class);
|
_log = util.getContext().logManager().getLog(Storage.class);
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
// Create names, rafs and lengths arrays.
|
// Create names, rafs and lengths arrays.
|
||||||
@@ -305,24 +314,15 @@ public class Storage
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param file canonical path (non-directory)
|
* @param file non-canonical path (non-directory)
|
||||||
* @return number of bytes remaining; -1 if unknown file
|
* @return number of bytes remaining; -1 if unknown file
|
||||||
* @since 0.7.14
|
* @since 0.7.14
|
||||||
*/
|
*/
|
||||||
public long remaining(String file) {
|
public long remaining(File file) {
|
||||||
long bytes = 0;
|
long bytes = 0;
|
||||||
for (TorrentFile tf : _torrentFiles) {
|
for (TorrentFile tf : _torrentFiles) {
|
||||||
File f = tf.RAFfile;
|
File f = tf.RAFfile;
|
||||||
// use canonical in case snark dir or sub dirs are symlinked
|
if (f.equals(file)) {
|
||||||
String canonical = null;
|
|
||||||
if (f != null) {
|
|
||||||
try {
|
|
||||||
canonical = f.getCanonicalPath();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
f = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (f != null && canonical.equals(file)) {
|
|
||||||
if (complete())
|
if (complete())
|
||||||
return 0;
|
return 0;
|
||||||
int psz = piece_size;
|
int psz = piece_size;
|
||||||
@@ -348,22 +348,16 @@ public class Storage
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param file canonical path (non-directory)
|
* @param file non-canonical path (non-directory)
|
||||||
* @since 0.8.1
|
* @since 0.8.1
|
||||||
*/
|
*/
|
||||||
public int getPriority(String file) {
|
public int getPriority(File file) {
|
||||||
if (complete() || metainfo.getFiles() == null)
|
if (complete() || metainfo.getFiles() == null)
|
||||||
return 0;
|
return 0;
|
||||||
for (TorrentFile tf : _torrentFiles) {
|
for (TorrentFile tf : _torrentFiles) {
|
||||||
File f = tf.RAFfile;
|
File f = tf.RAFfile;
|
||||||
// use canonical in case snark dir or sub dirs are symlinked
|
if (f.equals(file))
|
||||||
if (f != null) {
|
return tf.priority;
|
||||||
try {
|
|
||||||
String canonical = f.getCanonicalPath();
|
|
||||||
if (canonical.equals(file))
|
|
||||||
return tf.priority;
|
|
||||||
} catch (IOException ioe) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -371,24 +365,18 @@ public class Storage
|
|||||||
/**
|
/**
|
||||||
* Must call Snark.updatePiecePriorities()
|
* Must call Snark.updatePiecePriorities()
|
||||||
* (which calls getPiecePriorities()) after calling this.
|
* (which calls getPiecePriorities()) after calling this.
|
||||||
* @param file canonical path (non-directory)
|
* @param file non-canonical path (non-directory)
|
||||||
* @param pri default 0; <0 to disable
|
* @param pri default 0; <0 to disable
|
||||||
* @since 0.8.1
|
* @since 0.8.1
|
||||||
*/
|
*/
|
||||||
public void setPriority(String file, int pri) {
|
public void setPriority(File file, int pri) {
|
||||||
if (complete() || metainfo.getFiles() == null)
|
if (complete() || metainfo.getFiles() == null)
|
||||||
return;
|
return;
|
||||||
for (TorrentFile tf : _torrentFiles) {
|
for (TorrentFile tf : _torrentFiles) {
|
||||||
File f = tf.RAFfile;
|
File f = tf.RAFfile;
|
||||||
// use canonical in case snark dir or sub dirs are symlinked
|
if (f.equals(file)) {
|
||||||
if (f != null) {
|
tf.priority = pri;
|
||||||
try {
|
return;
|
||||||
String canonical = f.getCanonicalPath();
|
|
||||||
if (canonical.equals(file)) {
|
|
||||||
tf.priority = pri;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (IOException ioe) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -490,9 +478,9 @@ public class Storage
|
|||||||
* Creates (and/or checks) all files from the metainfo file list.
|
* Creates (and/or checks) all files from the metainfo file list.
|
||||||
* Only call this once, and only after the constructor with the metainfo.
|
* Only call this once, and only after the constructor with the metainfo.
|
||||||
*/
|
*/
|
||||||
public void check(String rootDir) throws IOException
|
public void check() throws IOException
|
||||||
{
|
{
|
||||||
check(rootDir, 0, null);
|
check(0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -500,14 +488,9 @@ public class Storage
|
|||||||
* Use a saved bitfield and timestamp from a config file.
|
* Use a saved bitfield and timestamp from a config file.
|
||||||
* Only call this once, and only after the constructor with the metainfo.
|
* Only call this once, and only after the constructor with the metainfo.
|
||||||
*/
|
*/
|
||||||
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
|
public void check(long savedTime, BitField savedBitField) throws IOException
|
||||||
{
|
{
|
||||||
File base;
|
|
||||||
boolean areFilesPublic = _util.getFilesPublic();
|
boolean areFilesPublic = _util.getFilesPublic();
|
||||||
if (areFilesPublic)
|
|
||||||
base = new File(rootDir, filterName(metainfo.getName()));
|
|
||||||
else
|
|
||||||
base = new SecureFile(rootDir, filterName(metainfo.getName()));
|
|
||||||
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
|
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
|
||||||
|
|
||||||
if (!_torrentFiles.isEmpty())
|
if (!_torrentFiles.isEmpty())
|
||||||
@@ -517,16 +500,16 @@ public class Storage
|
|||||||
{
|
{
|
||||||
// Create base as file.
|
// Create base as file.
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Creating/Checking file: " + base);
|
_log.info("Creating/Checking file: " + _base);
|
||||||
if (!base.createNewFile() && !base.exists())
|
if (!_base.createNewFile() && !_base.exists())
|
||||||
throw new IOException("Could not create file " + base);
|
throw new IOException("Could not create file " + _base);
|
||||||
|
|
||||||
_torrentFiles.add(new TorrentFile(base, base, metainfo.getTotalLength()));
|
_torrentFiles.add(new TorrentFile(_base, _base, metainfo.getTotalLength()));
|
||||||
if (useSavedBitField) {
|
if (useSavedBitField) {
|
||||||
long lm = base.lastModified();
|
long lm = _base.lastModified();
|
||||||
if (lm <= 0 || lm > savedTime)
|
if (lm <= 0 || lm > savedTime)
|
||||||
useSavedBitField = false;
|
useSavedBitField = false;
|
||||||
else if (base.length() != metainfo.getTotalLength())
|
else if (_base.length() != metainfo.getTotalLength())
|
||||||
useSavedBitField = false;
|
useSavedBitField = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,9 +517,9 @@ public class Storage
|
|||||||
{
|
{
|
||||||
// Create base as dir.
|
// Create base as dir.
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Creating/Checking directory: " + base);
|
_log.info("Creating/Checking directory: " + _base);
|
||||||
if (!base.mkdir() && !base.isDirectory())
|
if (!_base.mkdir() && !_base.isDirectory())
|
||||||
throw new IOException("Could not create directory " + base);
|
throw new IOException("Could not create directory " + _base);
|
||||||
|
|
||||||
List<Long> ls = metainfo.getLengths();
|
List<Long> ls = metainfo.getLengths();
|
||||||
int size = files.size();
|
int size = files.size();
|
||||||
@@ -544,7 +527,7 @@ public class Storage
|
|||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
List<String> path = files.get(i);
|
List<String> path = files.get(i);
|
||||||
File f = createFileFromNames(base, path, areFilesPublic);
|
File f = createFileFromNames(_base, path, areFilesPublic);
|
||||||
// dup file name check after filtering
|
// dup file name check after filtering
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
if (f.equals(_torrentFiles.get(j).RAFfile)) {
|
if (f.equals(_torrentFiles.get(j).RAFfile)) {
|
||||||
@@ -560,12 +543,12 @@ public class Storage
|
|||||||
else
|
else
|
||||||
lastPath = '_' + lastPath;
|
lastPath = '_' + lastPath;
|
||||||
path.set(last, lastPath);
|
path.set(last, lastPath);
|
||||||
f = createFileFromNames(base, path, areFilesPublic);
|
f = createFileFromNames(_base, path, areFilesPublic);
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long len = ls.get(i).longValue();
|
long len = ls.get(i).longValue();
|
||||||
_torrentFiles.add(new TorrentFile(base, f, len));
|
_torrentFiles.add(new TorrentFile(_base, f, len));
|
||||||
total += len;
|
total += len;
|
||||||
if (useSavedBitField) {
|
if (useSavedBitField) {
|
||||||
long lm = f.lastModified();
|
long lm = f.lastModified();
|
||||||
@@ -612,7 +595,7 @@ public class Storage
|
|||||||
* @param rootDir ignored
|
* @param rootDir ignored
|
||||||
* @throws IOE on fail
|
* @throws IOE on fail
|
||||||
*/
|
*/
|
||||||
public void reopen(String rootDir) throws IOException
|
public void reopen() throws IOException
|
||||||
{
|
{
|
||||||
if (_torrentFiles.isEmpty())
|
if (_torrentFiles.isEmpty())
|
||||||
throw new IOException("Storage not checked yet");
|
throw new IOException("Storage not checked yet");
|
||||||
@@ -688,6 +671,8 @@ public class Storage
|
|||||||
* Note that filtering each path element individually may lead to
|
* Note that filtering each path element individually may lead to
|
||||||
* things going in the wrong place if there are duplicates
|
* things going in the wrong place if there are duplicates
|
||||||
* in intermediate path elements after filtering.
|
* in intermediate path elements after filtering.
|
||||||
|
*
|
||||||
|
* @param names path elements
|
||||||
*/
|
*/
|
||||||
private static File createFileFromNames(File base, List<String> names, boolean areFilesPublic) throws IOException
|
private static File createFileFromNames(File base, List<String> names, boolean areFilesPublic) throws IOException
|
||||||
{
|
{
|
||||||
@@ -721,15 +706,46 @@ public class Storage
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getFileFromNames(File base, List<String> names)
|
/**
|
||||||
{
|
* The base file or directory.
|
||||||
Iterator<String> it = names.iterator();
|
* @return a new List
|
||||||
while (it.hasNext())
|
*/
|
||||||
{
|
public File getBase() {
|
||||||
String name = filterName(it.next());
|
return _base;
|
||||||
base = new File(base, name);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not include directories. Unsorted.
|
||||||
|
* @since 0.9.10
|
||||||
|
* @return a new List
|
||||||
|
*/
|
||||||
|
public List<File> getFiles() {
|
||||||
|
List<File> rv = new ArrayList<File>(_torrentFiles.size());
|
||||||
|
for (TorrentFile tf : _torrentFiles) {
|
||||||
|
rv.add(tf.RAFfile);
|
||||||
}
|
}
|
||||||
return base;
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes the base for a multi-file torrent.
|
||||||
|
* Sorted bottom-up for easy deletion.
|
||||||
|
* Slow. Use for deletion only.
|
||||||
|
* @since 0.9.10
|
||||||
|
* @return a new Set or null for a single-file torrent
|
||||||
|
*/
|
||||||
|
public SortedSet<File> getDirectories() {
|
||||||
|
if (!_base.isDirectory())
|
||||||
|
return null;
|
||||||
|
SortedSet<File> rv = new TreeSet<File>(Collections.reverseOrder());
|
||||||
|
rv.add(_base);
|
||||||
|
for (TorrentFile tf : _torrentFiles) {
|
||||||
|
File f = tf.RAFfile;
|
||||||
|
do {
|
||||||
|
f = f.getParentFile();
|
||||||
|
} while (f != null && rv.add(f));
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -17,7 +17,6 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import javax.servlet.ServletConfig;
|
import javax.servlet.ServletConfig;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
@@ -828,42 +827,36 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
_manager.addMessage(_("Data file could not be deleted: {0}", f.getAbsolutePath()));
|
_manager.addMessage(_("Data file could not be deleted: {0}", f.getAbsolutePath()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Storage storage = snark.getStorage();
|
||||||
|
if (storage == null)
|
||||||
|
break;
|
||||||
// step 1 delete files
|
// step 1 delete files
|
||||||
for (int i = 0; i < files.size(); i++) {
|
for (File df : storage.getFiles()) {
|
||||||
// multifile torrents have the getFiles() return lists of lists of filenames, but
|
|
||||||
// each of those lists just contain a single file afaict...
|
|
||||||
File df = Storage.getFileFromNames(f, files.get(i));
|
|
||||||
if (df.delete()) {
|
if (df.delete()) {
|
||||||
//_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
|
//_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
|
||||||
} else {
|
} else {
|
||||||
_manager.addMessage(_("Data file could not be deleted: {0}", df.getAbsolutePath()));
|
_manager.addMessage(_("Data file could not be deleted: {0}", df.getAbsolutePath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// step 2 make Set of dirs with reverse sort
|
// step 2 delete dirs bottom-up
|
||||||
Set<File> dirs = new TreeSet<File>(Collections.reverseOrder());
|
Set<File> dirs = storage.getDirectories();
|
||||||
for (List<String> list : files) {
|
if (_log.shouldLog(Log.INFO))
|
||||||
for (int i = 1; i < list.size(); i++) {
|
_log.info("Dirs to delete: " + DataHelper.toString(dirs));
|
||||||
dirs.add(Storage.getFileFromNames(f, list.subList(0, i)));
|
boolean ok = false;
|
||||||
}
|
|
||||||
}
|
|
||||||
// step 3 delete dirs bottom-up
|
|
||||||
for (File df : dirs) {
|
for (File df : dirs) {
|
||||||
if (df.delete()) {
|
if (df.delete()) {
|
||||||
|
ok = true;
|
||||||
//_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
|
//_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
|
||||||
} else {
|
} else {
|
||||||
|
ok = false;
|
||||||
_manager.addMessage(_("Directory could not be deleted: {0}", df.getAbsolutePath()));
|
_manager.addMessage(_("Directory could not be deleted: {0}", df.getAbsolutePath()));
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Could not delete dir " + df);
|
_log.warn("Could not delete dir " + df);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// step 4 delete base
|
// step 3 message for base (last one)
|
||||||
if (f.delete()) {
|
if (ok)
|
||||||
_manager.addMessage(_("Directory deleted: {0}", f.getAbsolutePath()));
|
_manager.addMessage(_("Directory deleted: {0}", storage.getBase()));
|
||||||
} else {
|
|
||||||
_manager.addMessage(_("Directory could not be deleted: {0}", f.getAbsolutePath()));
|
|
||||||
if (_log.shouldLog(Log.WARN))
|
|
||||||
_log.warn("Could not delete dir " + f);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2462,6 +2455,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
boolean complete = false;
|
boolean complete = false;
|
||||||
String status = "";
|
String status = "";
|
||||||
long length = item.length();
|
long length = item.length();
|
||||||
|
int priority = 0;
|
||||||
if (item.isDirectory()) {
|
if (item.isDirectory()) {
|
||||||
complete = true;
|
complete = true;
|
||||||
//status = toImg("tick") + ' ' + _("Directory");
|
//status = toImg("tick") + ' ' + _("Directory");
|
||||||
@@ -2472,9 +2466,8 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
status = toImg("cancel") + ' ' + _("Torrent not found?");
|
status = toImg("cancel") + ' ' + _("Torrent not found?");
|
||||||
} else {
|
} else {
|
||||||
Storage storage = snark.getStorage();
|
Storage storage = snark.getStorage();
|
||||||
try {
|
|
||||||
File f = item;
|
long remaining = storage.remaining(item);
|
||||||
long remaining = storage.remaining(f.getCanonicalPath());
|
|
||||||
if (remaining < 0) {
|
if (remaining < 0) {
|
||||||
complete = true;
|
complete = true;
|
||||||
status = toImg("cancel") + ' ' + _("File not found in torrent?");
|
status = toImg("cancel") + ' ' + _("File not found in torrent?");
|
||||||
@@ -2482,7 +2475,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
complete = true;
|
complete = true;
|
||||||
status = toImg("tick") + ' ' + _("Complete");
|
status = toImg("tick") + ' ' + _("Complete");
|
||||||
} else {
|
} else {
|
||||||
int priority = storage.getPriority(f.getCanonicalPath());
|
priority = storage.getPriority(item);
|
||||||
if (priority < 0)
|
if (priority < 0)
|
||||||
status = toImg("cancel");
|
status = toImg("cancel");
|
||||||
else if (priority == 0)
|
else if (priority == 0)
|
||||||
@@ -2493,9 +2486,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
(100 * (length - remaining) / length) + "% " + _("complete") +
|
(100 * (length - remaining) / length) + "% " + _("complete") +
|
||||||
" (" + DataHelper.formatSize2(remaining) + "B " + _("remaining") + ")";
|
" (" + DataHelper.formatSize2(remaining) + "B " + _("remaining") + ")";
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
|
||||||
status = "Not a file? " + ioe;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2534,21 +2525,19 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
buf.append("</TD>");
|
buf.append("</TD>");
|
||||||
if (showPriority) {
|
if (showPriority) {
|
||||||
buf.append("<td class=\"priority\">");
|
buf.append("<td class=\"priority\">");
|
||||||
File f = item;
|
|
||||||
if ((!complete) && (!item.isDirectory())) {
|
if ((!complete) && (!item.isDirectory())) {
|
||||||
int pri = snark.getStorage().getPriority(f.getCanonicalPath());
|
buf.append("<input type=\"radio\" value=\"5\" name=\"pri.").append(item).append("\" ");
|
||||||
buf.append("<input type=\"radio\" value=\"5\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
|
if (priority > 0)
|
||||||
if (pri > 0)
|
|
||||||
buf.append("checked=\"true\"");
|
buf.append("checked=\"true\"");
|
||||||
buf.append('>').append(_("High"));
|
buf.append('>').append(_("High"));
|
||||||
|
|
||||||
buf.append("<input type=\"radio\" value=\"0\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
|
buf.append("<input type=\"radio\" value=\"0\" name=\"pri.").append(item).append("\" ");
|
||||||
if (pri == 0)
|
if (priority == 0)
|
||||||
buf.append("checked=\"true\"");
|
buf.append("checked=\"true\"");
|
||||||
buf.append('>').append(_("Normal"));
|
buf.append('>').append(_("Normal"));
|
||||||
|
|
||||||
buf.append("<input type=\"radio\" value=\"-9\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
|
buf.append("<input type=\"radio\" value=\"-9\" name=\"pri.").append(item).append("\" ");
|
||||||
if (pri < 0)
|
if (priority < 0)
|
||||||
buf.append("checked=\"true\"");
|
buf.append("checked=\"true\"");
|
||||||
buf.append('>').append(_("Skip"));
|
buf.append('>').append(_("Skip"));
|
||||||
showSaveButton = true;
|
showSaveButton = true;
|
||||||
@@ -2643,7 +2632,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
if (key.startsWith("pri.")) {
|
if (key.startsWith("pri.")) {
|
||||||
try {
|
try {
|
||||||
String file = key.substring(4);
|
File file = new File(key.substring(4));
|
||||||
String val = entry.getValue()[0]; // jetty arrays
|
String val = entry.getValue()[0]; // jetty arrays
|
||||||
int pri = Integer.parseInt(val);
|
int pri = Integer.parseInt(val);
|
||||||
storage.setPriority(file, pri);
|
storage.setPriority(file, pri);
|
||||||
|
Reference in New Issue
Block a user