diff --git a/core/persisted.bak b/core/persisted.bak deleted file mode 100644 index abf60db1..00000000 --- a/core/persisted.bak +++ /dev/null @@ -1 +0,0 @@ -{"file":"AC8vVXNlcnMvemFiL2RldnN0dWZmL211d2lyZS9jb3JlL3NoYXJlZERpci9maWxlMQ==","length":1,"infoHash":"FAbgWIHimTZ3ZtMT4mwFVk7JG~ch0xcmvW5G5gaJU5o=","hashList":["bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0="]} \ No newline at end of file diff --git a/core/src/main/groovy/com/muwire/core/download/Downloader.groovy b/core/src/main/groovy/com/muwire/core/download/Downloader.groovy index 82ff783f..0da1cb98 100644 --- a/core/src/main/groovy/com/muwire/core/download/Downloader.groovy +++ b/core/src/main/groovy/com/muwire/core/download/Downloader.groovy @@ -135,7 +135,7 @@ abstract class Downloader { protected void fireEvent(Set successfulDestinations, boolean confidential) { def event = new FileDownloadedEvent( downloadedFile: new DownloadedFile(file.getCanonicalFile(), infoHash.getRoot(), - pieceSizePow2, successfulDestinations), + pieceSizePow2, System.currentTimeMillis(), successfulDestinations), parentToShare: toShare, downloader: this, infoHash: infoHash, diff --git a/core/src/main/groovy/com/muwire/core/files/BasePersisterService.groovy b/core/src/main/groovy/com/muwire/core/files/BasePersisterService.groovy index fb1c2c33..e12382d0 100644 --- a/core/src/main/groovy/com/muwire/core/files/BasePersisterService.groovy +++ b/core/src/main/groovy/com/muwire/core/files/BasePersisterService.groovy @@ -15,7 +15,7 @@ import java.util.stream.Collectors abstract class BasePersisterService extends Service{ - protected static FileLoadedEvent fromJson(def json) { + protected static FileLoadedEvent fromJson(def json, long sharedTime) { if (json.file == null || json.length == null || json.infoHash == null || json.hashList == null) throw new IllegalArgumentException() if (!(json.hashList instanceof List)) @@ -53,13 +53,13 @@ abstract class BasePersisterService extends Service{ if (json.sources != null) { List sources = (List)json.sources Set sourceSet = sources.stream().map({ d -> new Destination(d.toString())}).collect Collectors.toSet() - DownloadedFile df = new DownloadedFile(file, ih.getRoot(), pieceSize, sourceSet) + DownloadedFile df = new DownloadedFile(file, ih.getRoot(), pieceSize, sharedTime, sourceSet) df.setComment(json.comment) return new FileLoadedEvent(loadedFile : df, infoHash: ih) } - SharedFile sf = new SharedFile(file, ih.getRoot(), pieceSize) + SharedFile sf = new SharedFile(file, ih.getRoot(), pieceSize, sharedTime) sf.setComment(json.comment) if (json.downloaders != null) json.downloaders.each {sf.addDownloader(it)} @@ -77,7 +77,7 @@ abstract class BasePersisterService extends Service{ } - protected static FileLoadedEvent fromJsonLite(json) { + protected static FileLoadedEvent fromJsonLite(json, long fileTime) { if (json.file == null || json.length == null || json.root == null) throw new IllegalArgumentException() @@ -105,11 +105,15 @@ abstract class BasePersisterService extends Service{ Path path = null if (json.pathToSharedParent != null) path = Path.of(json.pathToSharedParent) - + + long sharedTime = fileTime + if (json.sharedTime != null) + sharedTime = json.sharedTime + if (json.sources != null) { List sources = (List)json.sources Set sourceSet = sources.stream().map({ d -> new Destination(d.toString())}).collect Collectors.toSet() - DownloadedFile df = new DownloadedFile(file, ih.getRoot(), pieceSize, sourceSet) + DownloadedFile df = new DownloadedFile(file, ih.getRoot(), pieceSize, sharedTime, sourceSet) if (published) df.publish(publishedTimestamp) df.setComment(json.comment) @@ -117,8 +121,7 @@ abstract class BasePersisterService extends Service{ return new FileLoadedEvent(loadedFile : df, infoHash: ih) } - - SharedFile sf = new SharedFile(file, ih.getRoot(), pieceSize) + SharedFile sf = new SharedFile(file, ih.getRoot(), pieceSize, sharedTime) sf.setPathToSharedParent(path) sf.setComment(json.comment) if (published) @@ -152,6 +155,7 @@ abstract class BasePersisterService extends Service{ json.comment = sf.getComment() json.hits = sf.getHits() json.downloaders = sf.getDownloaders() + json.sharedTime = sf.getSharedTime() if (sf.getPathToSharedParent() != null) json.pathToSharedParent = sf.getPathToSharedParent().toString() diff --git a/core/src/main/groovy/com/muwire/core/files/HasherService.groovy b/core/src/main/groovy/com/muwire/core/files/HasherService.groovy index 1fed1d1c..462811ce 100644 --- a/core/src/main/groovy/com/muwire/core/files/HasherService.groovy +++ b/core/src/main/groovy/com/muwire/core/files/HasherService.groovy @@ -140,7 +140,8 @@ class HasherService { eventBus.publish new InfoHashEvent(file: canonical, infoHash: hash) } else log.fine("found an existing hash list for $f => $canonical") - def sf = new SharedFile(f, hash.getRoot(), FileHasher.getPieceSize(f.length())) + def sf = new SharedFile(f, hash.getRoot(), FileHasher.getPieceSize(f.length()), + System.currentTimeMillis()) eventBus.publish new FileHashedEvent(sharedFile: sf) } } finally { diff --git a/core/src/main/groovy/com/muwire/core/files/PersisterFolderService.groovy b/core/src/main/groovy/com/muwire/core/files/PersisterFolderService.groovy index 1b889e96..1f2c00c3 100644 --- a/core/src/main/groovy/com/muwire/core/files/PersisterFolderService.groovy +++ b/core/src/main/groovy/com/muwire/core/files/PersisterFolderService.groovy @@ -223,8 +223,9 @@ class PersisterFolderService extends BasePersisterService { log.fine("processing path $it") def slurper = new JsonSlurper(type: JsonParserType.LAX) try { - def parsed = slurper.parse(it.toFile()) - def event = fromJsonLite parsed + File file = it.toFile() + def parsed = slurper.parse(file) + def event = fromJsonLite(parsed, file.lastModified()) if (event == null) return if (core.muOptions.ignoredFileTypes.contains(DataUtil.getFileExtension(event.loadedFile.file))) { diff --git a/core/src/main/groovy/com/muwire/core/files/PersisterService.groovy b/core/src/main/groovy/com/muwire/core/files/PersisterService.groovy index d0fe7348..ad3b7bc5 100644 --- a/core/src/main/groovy/com/muwire/core/files/PersisterService.groovy +++ b/core/src/main/groovy/com/muwire/core/files/PersisterService.groovy @@ -54,10 +54,11 @@ class PersisterService extends BasePersisterService { int loaded = 0 def slurper = new JsonSlurper() try { + final long sharedTime = location.lastModified() location.eachLine { if (it.trim().length() > 0) { def parsed = slurper.parseText it - def event = fromJson parsed + def event = fromJson(parsed, sharedTime) if (event != null) { log.fine("loaded file $event.loadedFile.file") event.source = "PersisterService" diff --git a/core/src/main/java/com/muwire/core/DownloadedFile.java b/core/src/main/java/com/muwire/core/DownloadedFile.java index 7a7faaa2..752ec54e 100644 --- a/core/src/main/java/com/muwire/core/DownloadedFile.java +++ b/core/src/main/java/com/muwire/core/DownloadedFile.java @@ -10,9 +10,9 @@ public class DownloadedFile extends SharedFile { private final Set sources; - public DownloadedFile(File file, byte[] root, int pieceSize, Set sources) + public DownloadedFile(File file, byte[] root, int pieceSize, long sharedTime, Set sources) throws IOException { - super(file, root, pieceSize); + super(file, root, pieceSize, sharedTime); this.sources = sources; } diff --git a/core/src/main/java/com/muwire/core/SharedFile.java b/core/src/main/java/com/muwire/core/SharedFile.java index 40697ee8..aff41c7a 100644 --- a/core/src/main/java/com/muwire/core/SharedFile.java +++ b/core/src/main/java/com/muwire/core/SharedFile.java @@ -16,6 +16,7 @@ public class SharedFile { private final byte[] root; private final InfoHash rootInfoHash; private final int pieceSize; + private final long sharedTime; private volatile VisualCache visualCache; private final int hashCode; @@ -28,11 +29,12 @@ public class SharedFile { /** Path to the top-most parent File that is shared. Null if no such exists */ private volatile Path pathToSharedParent; - public SharedFile(File file, byte[] root, int pieceSize) throws IOException { + public SharedFile(File file, byte[] root, int pieceSize, long sharedTime) throws IOException { this.file = file; this.root = root; this.rootInfoHash = new InfoHash(root); this.pieceSize = pieceSize; + this.sharedTime = sharedTime; this.hashCode = Arrays.hashCode(root) ^ file.hashCode(); } @@ -40,6 +42,14 @@ public class SharedFile { return file; } + public boolean isStale() { + return sharedTime < file.lastModified(); + } + + public long getSharedTime() { + return sharedTime; + } + private byte[] getPathHash() throws NoSuchAlgorithmException { MessageDigest digester = MessageDigest.getInstance("SHA-256"); digester.update(file.getAbsolutePath().getBytes()); diff --git a/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy b/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy index a2b2cfa8..9e73c60d 100644 --- a/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy +++ b/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy @@ -43,7 +43,7 @@ class FileManagerTest { void testHash1Result() { File f = new File("a b.c") byte [] root = new byte[32] - SharedFile sf = new SharedFile(f,root, 0) + SharedFile sf = new SharedFile(f,root, 0, 0L) FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) manager.onFileHashedEvent(fhe) @@ -62,8 +62,8 @@ class FileManagerTest { @Test void testHash2Results() { byte [] root = new byte[32] - SharedFile sf1 = new SharedFile(new File("a b.c"), root, 0) - SharedFile sf2 = new SharedFile(new File("d e.f"), root, 0) + SharedFile sf1 = new SharedFile(new File("a b.c"), root, 0, 0L) + SharedFile sf2 = new SharedFile(new File("d e.f"), root, 0, 0L) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf1) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf2) @@ -84,7 +84,7 @@ class FileManagerTest { void testHash0Results() { File f = new File("a b.c") InfoHash ih = InfoHash.fromHashList(new byte[32]) - SharedFile sf = new SharedFile(f,ih.getRoot(), 0) + SharedFile sf = new SharedFile(f,ih.getRoot(), 0, 0L) FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) manager.onFileHashedEvent(fhe) @@ -98,7 +98,7 @@ class FileManagerTest { void testKeyword1Result() { File f = new File("a b.c") InfoHash ih = InfoHash.fromHashList(new byte[32]) - SharedFile sf = new SharedFile(f,ih.getRoot(),0) + SharedFile sf = new SharedFile(f,ih.getRoot(),0, 0L) FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) manager.onFileHashedEvent(fhe) @@ -118,12 +118,12 @@ class FileManagerTest { void testKeyword2Results() { File f1 = new File("a b.c") InfoHash ih1 = InfoHash.fromHashList(new byte[32]) - SharedFile sf1 = new SharedFile(f1, ih1.getRoot(), 0) + SharedFile sf1 = new SharedFile(f1, ih1.getRoot(), 0, 0L) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile: sf1) File f2 = new File("c d.e") InfoHash ih2 = InfoHash.fromHashList(new byte[64]) - SharedFile sf2 = new SharedFile(f2, ih2.getRoot(), 0) + SharedFile sf2 = new SharedFile(f2, ih2.getRoot(), 0, 0L) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile: sf2) Thread.sleep(50) @@ -143,7 +143,7 @@ class FileManagerTest { void testKeyword0Results() { File f = new File("a b.c") InfoHash ih = InfoHash.fromHashList(new byte[32]) - SharedFile sf = new SharedFile(f,ih.getRoot(),0) + SharedFile sf = new SharedFile(f,ih.getRoot(),0, 0L) FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) manager.onFileHashedEvent(fhe) @@ -156,8 +156,8 @@ class FileManagerTest { @Test void testRemoveFileExistingHash() { InfoHash ih = InfoHash.fromHashList(new byte[32]) - SharedFile sf1 = new SharedFile(new File("a b.c"), ih.getRoot(), 0) - SharedFile sf2 = new SharedFile(new File("d e.f"), ih.getRoot(), 0) + SharedFile sf1 = new SharedFile(new File("a b.c"), ih.getRoot(), 0, 0L) + SharedFile sf2 = new SharedFile(new File("d e.f"), ih.getRoot(), 0, 0L) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf1) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf2) @@ -174,12 +174,12 @@ class FileManagerTest { void testRemoveFile() { File f1 = new File("a b.c") InfoHash ih1 = InfoHash.fromHashList(new byte[32]) - SharedFile sf1 = new SharedFile(f1, ih1.getRoot(), 0) + SharedFile sf1 = new SharedFile(f1, ih1.getRoot(), 0, 0L) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile: sf1) File f2 = new File("c d.e") InfoHash ih2 = InfoHash.fromHashList(new byte[64]) - SharedFile sf2 = new SharedFile(f2, ih2.getRoot(), 0) + SharedFile sf2 = new SharedFile(f2, ih2.getRoot(), 0, 0L) manager.onFileLoadedEvent new FileLoadedEvent(loadedFile: sf2) Thread.sleep(50) @@ -207,7 +207,7 @@ class FileManagerTest { comment = Base64.encode(DataUtil.encodei18nString(comment)) File f1 = new File("MuWire-0.5.10.AppImage") InfoHash ih1 = InfoHash.fromHashList(new byte[32]) - SharedFile sf1 = new SharedFile(f1, ih1.getRoot(), 0) + SharedFile sf1 = new SharedFile(f1, ih1.getRoot(), 0, 0L) sf1.setComment(comment) manager.onFileLoadedEvent(new FileLoadedEvent(loadedFile : sf1)) @@ -215,7 +215,7 @@ class FileManagerTest { File f2 = new File("MuWire-0.6.0.AppImage") InfoHash ih2 = InfoHash.fromHashList(new byte[64]) - SharedFile sf2 = new SharedFile(f2, ih2.getRoot(), 0) + SharedFile sf2 = new SharedFile(f2, ih2.getRoot(), 0, 0L) sf2.setComment(comment) manager.onFileLoadedEvent(new FileLoadedEvent(loadedFile : sf2)) diff --git a/core/src/test/groovy/com/muwire/core/files/PersisterServiceSavingTest.groovy b/core/src/test/groovy/com/muwire/core/files/PersisterServiceSavingTest.groovy index 0b1bc296..435c206f 100644 --- a/core/src/test/groovy/com/muwire/core/files/PersisterServiceSavingTest.groovy +++ b/core/src/test/groovy/com/muwire/core/files/PersisterServiceSavingTest.groovy @@ -57,7 +57,7 @@ class PersisterServiceSavingTest { @Test void testSavingSharedFile() { - sf = new SharedFile(f, ih, 0) + sf = new SharedFile(f, ih, 0, 0L) ps = new PersisterService(persisted, eventBus, 100, fileSource) ps.onUILoadedEvent(null) @@ -76,7 +76,7 @@ class PersisterServiceSavingTest { @Test void testSavingDownloadedFile() { Destinations dests = new Destinations() - sf = new DownloadedFile(f, ih, 0, new HashSet([dests.dest1, dests.dest2])) + sf = new DownloadedFile(f, ih, 0, 0L, new HashSet([dests.dest1, dests.dest2])) ps = new PersisterService(persisted, eventBus, 100, fileSource) ps.onUILoadedEvent(null)