From d4992936b1d3865aa64fc3a03d9fd1c530822ea2 Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 14 Jul 2018 17:09:51 +0000 Subject: [PATCH] i2psnark: Recreate deleted files on recheck/reopen (ticket #2125) --- .../java/src/org/klomp/snark/Storage.java | 52 ++++++++++++++++--- history.txt | 3 ++ .../src/net/i2p/router/RouterVersion.java | 2 +- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 902ae8a373..91dd34261a 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -788,9 +788,29 @@ public class Storage implements Closeable { if (_torrentFiles.isEmpty()) throw new IOException("Storage not checked yet"); - for (TorrentFile tf : _torrentFiles) { - if (!tf.RAFfile.exists()) - throw new IOException("File does not exist: " + tf); + for (int i = 0; i < _torrentFiles.size(); i++) { + TorrentFile tf = _torrentFiles.get(i); + if (!tf.RAFfile.exists()) { + // File should exist when we get here, but could have vanished + List> files = metainfo.getFiles(); + if (files != null) { + createFileFromNames(_base, files.get(i), _util.getFilesPublic()); + } else { + if (!_base.createNewFile()) + throw new IOException("File '" + tf.name + "' was deleted, unable to recreate"); + } + synchronized(tf) { + tf.allocateFile(); + // close as we go so we don't run out of file descriptors + try { + tf.closeRAF(); + } catch (IOException ioe) {} + } + String msg = "File '" + tf.name + "' was deleted, must be downloaded again"; + if (listener != null) + listener.addMessage(msg); + _log.error(msg); + } } } @@ -1023,18 +1043,32 @@ public class Storage implements Closeable // Make sure all files are available and of correct length // The files should all exist as they have been created with zero length by createFilesFromNames() long lengthProgress = 0; - for (TorrentFile tf : _torrentFiles) - { + for (int i = 0; i < _torrentFiles.size(); i++) { + TorrentFile tf = _torrentFiles.get(i); long length = tf.RAFfile.length(); lengthProgress += tf.length; - if(tf.RAFfile.exists() && length == tf.length) - { + boolean exists = tf.RAFfile.exists(); + if (exists && length == tf.length) { if (listener != null) listener.storageAllocated(this, length); _checkProgress.set(0); resume = true; // XXX Could dynamicly check + } else if (length == 0) { + if (!exists) { + // File should exist when we get here, but could have vanished + // and we're now doing a recheck + List> files = metainfo.getFiles(); + if (files != null) { + createFileFromNames(_base, files.get(i), _util.getFilesPublic()); + } else { + if (!_base.createNewFile()) + throw new IOException("File '" + tf.name + "' was deleted, unable to recreate"); + } + String msg = "File '" + tf.name + "' was deleted, must be downloaded again"; + if (listener != null) + listener.addMessage(msg); + _log.error(msg); } - else if (length == 0) { changed = true; synchronized(tf) { allocateFile(tf); @@ -1506,6 +1540,8 @@ public class Storage implements Closeable * Sets isSparse[nr] = true. balloonFile(nr) should be called later to * defrag the file. * + * File MUST exist or will throw IOE + * * This calls openRAF(); caller must synchronize and call closeRAF(). */ public synchronized void allocateFile() throws IOException { diff --git a/history.txt b/history.txt index 893a3d7e0b..225aeb856e 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,6 @@ +2018-07-14 zzz + * i2psnark: Recreate deleted files on recheck/reopen (ticket #2125) + 2018-07-13 zzz * i2psnark: Add sequential order option (ticket #2234) diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 5a58b19bc2..e36cd3b143 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -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 = 11; + public final static long BUILD = 12; /** for example "-test" */ public final static String EXTRA = "";