priority persistence

This commit is contained in:
zzz
2010-10-15 17:25:45 +00:00
parent 9afff4f80a
commit 24dd78394b
3 changed files with 84 additions and 5 deletions

View File

@ -54,6 +54,7 @@ public class SnarkManager implements Snark.CompleteListener {
public static final String PROP_DIR = "i2psnark.dir";
public static final String PROP_META_PREFIX = "i2psnark.zmeta.";
public static final String PROP_META_BITFIELD_SUFFIX = ".bitfield";
public static final String PROP_META_PRIORITY_SUFFIX = ".priority";
private static final String CONFIG_FILE = "i2psnark.config";
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
@ -510,6 +511,7 @@ public class SnarkManager implements Snark.CompleteListener {
torrent = new Snark(_util, filename, null, -1, null, null, this,
_peerCoordinatorSet, _connectionAcceptor,
false, dataDir.getPath());
loadSavedFilePriorities(torrent);
torrent.completeListener = this;
synchronized (_snarks) {
_snarks.put(filename, torrent);
@ -587,6 +589,33 @@ public class SnarkManager implements Snark.CompleteListener {
return new BitField(bitfield, len);
}
/**
* Get the saved priorities for a torrent from the config file.
* @since 0.8.1
*/
public void loadSavedFilePriorities(Snark snark) {
MetaInfo metainfo = snark.meta;
if (metainfo.getFiles() == null)
return;
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
String pri = _config.getProperty(PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX);
if (pri == null)
return;
int filecount = metainfo.getFiles().size();
int[] rv = new int[filecount];
String[] arr = pri.split(",");
for (int i = 0; i < filecount && i < arr.length; i++) {
if (arr[i].length() > 0) {
try {
rv[i] = Integer.parseInt(arr[i]);
} catch (Throwable t) {}
}
}
snark.storage.setFilePriorities(rv);
}
/**
* Save the completion status of a torrent and the current time in the config file
* in the form "i2psnark.zmeta.$base64infohash=$time,$base64bitfield".
@ -595,8 +624,9 @@ public class SnarkManager implements Snark.CompleteListener {
* The time is a standard long converted to string.
* The status is either a bitfield converted to Base64 or "." for a completed
* torrent to save space in the config file and in memory.
* @param priorities may be null
*/
public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield) {
public void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities) {
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
@ -609,6 +639,34 @@ public class SnarkManager implements Snark.CompleteListener {
bfs = Base64.encode(bf);
}
_config.setProperty(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX, now + "," + bfs);
// now the file priorities
String prop = PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX;
if (priorities != null) {
boolean nonzero = false;
for (int i = 0; i < priorities.length; i++) {
if (priorities[i] != 0) {
nonzero = true;
break;
}
}
if (nonzero) {
// generate string like -5,,4,3,,,,,,-2 where no number is zero.
StringBuilder buf = new StringBuilder(2 * priorities.length);
for (int i = 0; i < priorities.length; i++) {
if (priorities[i] != 0)
buf.append(Integer.toString(priorities[i]));
if (i != priorities.length - 1)
buf.append(',');
}
_config.setProperty(prop, buf.toString());
} else {
_config.remove(prop);
}
} else {
_config.remove(prop);
}
saveConfig();
}
@ -621,6 +679,7 @@ public class SnarkManager implements Snark.CompleteListener {
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
_config.remove(PROP_META_PREFIX + infohash + PROP_META_BITFIELD_SUFFIX);
_config.remove(PROP_META_PREFIX + infohash + PROP_META_PRIORITY_SUFFIX);
saveConfig();
}
@ -742,7 +801,7 @@ public class SnarkManager implements Snark.CompleteListener {
}
public void updateStatus(Snark snark) {
saveTorrentStatus(snark.meta, snark.storage.getBitField());
saveTorrentStatus(snark.meta, snark.storage.getBitField(), snark.storage.getFilePriorities());
}
private void monitorTorrents(File dir) {

View File

@ -379,6 +379,25 @@ public class Storage
}
}
/**
* Get the file priorities array.
* @return null on error, if complete, or if only one file
* @since 0.8.1
*/
public int[] getFilePriorities() {
return priorities;
}
/**
* Set the file priorities array.
* Only call this when stopped, but after check()
* @param p may be null
* @since 0.8.1
*/
void setFilePriorities(int[] p) {
priorities = p;
}
/**
* Call setPriority() for all changed files first,
* then call this.
@ -389,7 +408,7 @@ public class Storage
* @since 0.8.1
*/
public int[] getPiecePriorities() {
if (complete() || metainfo.getFiles() == null)
if (complete() || metainfo.getFiles() == null || priorities == null)
return null;
int[] rv = new int[metainfo.getPieces()];
int file = 0;

View File

@ -503,7 +503,7 @@ public class I2PSnarkServlet extends Default {
File torrentFile = new File(baseFile.getParent(), baseFile.getName() + ".torrent");
if (torrentFile.exists())
throw new IOException("Cannot overwrite an existing .torrent file: " + torrentFile.getPath());
_manager.saveTorrentStatus(info, s.getBitField()); // so addTorrent won't recheck
_manager.saveTorrentStatus(info, s.getBitField(), null); // so addTorrent won't recheck
// DirMonitor could grab this first, maybe hold _snarks lock?
FileOutputStream out = new FileOutputStream(torrentFile);
out.write(info.getTorrentData());
@ -1498,7 +1498,7 @@ public class I2PSnarkServlet extends Default {
}
/** @since 0.8.1 */
private static void savePriorities(Snark snark, Map postParams) {
private void savePriorities(Snark snark, Map postParams) {
Set<Map.Entry> entries = postParams.entrySet();
for (Map.Entry entry : entries) {
String key = (String)entry.getKey();
@ -1514,6 +1514,7 @@ public class I2PSnarkServlet extends Default {
}
if (snark.coordinator != null)
snark.coordinator.updatePiecePriorities();
_manager.saveTorrentStatus(snark.storage.getMetaInfo(), snark.storage.getBitField(), snark.storage.getFilePriorities());
}