From 11167a291bc2542a1bb61d9c0c065ee2bf4b4351 Mon Sep 17 00:00:00 2001 From: Zlatin Balevsky Date: Sat, 21 Jul 2018 10:30:24 +0100 Subject: [PATCH] search and unsharing of files --- .../com/muwire/core/files/FileManager.groovy | 50 ++++- .../com/muwire/core/search/SearchEvent.groovy | 2 +- .../muwire/core/files/FileManagerTest.groovy | 179 ++++++++++++++++++ 3 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy diff --git a/core/src/main/groovy/com/muwire/core/files/FileManager.groovy b/core/src/main/groovy/com/muwire/core/files/FileManager.groovy index da8a52f0..2deb4611 100644 --- a/core/src/main/groovy/com/muwire/core/files/FileManager.groovy +++ b/core/src/main/groovy/com/muwire/core/files/FileManager.groovy @@ -4,6 +4,7 @@ import com.muwire.core.EventBus import com.muwire.core.SharedFile import com.muwire.core.search.ResultsEvent import com.muwire.core.search.SearchEvent +import com.muwire.core.search.SearchIndex class FileManager { @@ -11,13 +12,16 @@ class FileManager { final EventBus eventBus final Map> rootToFiles = new HashMap<>() final Map fileToSharedFile = new HashMap<>() + final Map> nameToFiles = new HashMap<>() + final SearchIndex index = new SearchIndex() FileManager(EventBus eventBus) { this.eventBus = eventBus } void onFileHashedEvent(FileHashedEvent e) { - addToIndex(e.sharedFile) + if (e.sharedFile != null) + addToIndex(e.sharedFile) } void onFileLoadedEvent(FileLoadedEvent e) { @@ -37,6 +41,41 @@ class FileManager { } existing.add(sf) fileToSharedFile.put(sf.file, sf) + + String name = sf.getFile().getName() + Set existingFiles = nameToFiles.get(name) + if (existingFiles == null) { + existingFiles = new HashSet<>() + nameToFiles.put(name, existingFiles) + } + existingFiles.add(sf.getFile()) + + index.add(name) + } + + void onFileUnsharedEvent(FileUnsharedEvent e) { + SharedFile sf = e.unsharedFile + byte [] root = sf.getInfoHash().getRoot() + Set existing = rootToFiles.get(root) + if (existing != null) { + existing.remove(sf) + if (existing.isEmpty()) { + rootToFiles.remove(root) + } + } + + fileToSharedFile.remove(sf.file) + + String name = sf.getFile().getName() + Set existingFiles = nameToFiles.get(name) + if (existingFiles != null) { + existingFiles.remove(sf.file) + if (existingFiles.isEmpty()) { + nameToFiles.remove(name) + } + } + + index.remove(name) } Map getSharedFiles() { @@ -52,7 +91,14 @@ class FileManager { if (found != null && !found.isEmpty()) re = new ResultsEvent(results: found.asList(), uuid: e.uuid) } else { - // TODO: keyword search + def names = index.search e.searchTerms + Set files = new HashSet<>() + names.each { files.addAll nameToFiles.getOrDefault(it, []) } + Set sharedFiles = new HashSet<>() + files.each { sharedFiles.add fileToSharedFile[it] } + if (!sharedFiles.isEmpty()) + re = new ResultsEvent(results: sharedFiles.asList(), uuid: e.uuid) + } if (re != null) diff --git a/core/src/main/groovy/com/muwire/core/search/SearchEvent.groovy b/core/src/main/groovy/com/muwire/core/search/SearchEvent.groovy index 0d6c910b..5be1115a 100644 --- a/core/src/main/groovy/com/muwire/core/search/SearchEvent.groovy +++ b/core/src/main/groovy/com/muwire/core/search/SearchEvent.groovy @@ -4,7 +4,7 @@ import com.muwire.core.Event class SearchEvent extends Event { - String[] searchTerms + List searchTerms byte [] searchHash UUID uuid } diff --git a/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy b/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy new file mode 100644 index 00000000..1b4f5d78 --- /dev/null +++ b/core/src/test/groovy/com/muwire/core/files/FileManagerTest.groovy @@ -0,0 +1,179 @@ +package com.muwire.core.files + +import org.junit.Before +import org.junit.Test + +import com.muwire.core.EventBus +import com.muwire.core.InfoHash +import com.muwire.core.SharedFile +import com.muwire.core.search.ResultsEvent +import com.muwire.core.search.SearchEvent + +class FileManagerTest { + + EventBus eventBus + + FileManager manager + ResultsEvent results + + def listener = new Object() { + void onResultsEvent(ResultsEvent e) { + results = e + } + } + + @Before + void before() { + eventBus = new EventBus() + eventBus.register(ResultsEvent.class, listener) + manager = new FileManager(eventBus) + results = null + } + + @Test + void testHash1Result() { + File f = new File("a b.c") + InfoHash ih = InfoHash.fromHashList(new byte[32]) + SharedFile sf = new SharedFile(f,ih) + FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) + manager.onFileHashedEvent(fhe) + + UUID uuid = UUID.randomUUID() + SearchEvent se = new SearchEvent(searchHash: ih.getRoot(), uuid: uuid) + + manager.onSearchEvent(se) + + assert results != null + assert results.results.size() == 1 + assert results.results.contains(sf) + assert results.uuid == uuid + } + + @Test + void testHash2Results() { + InfoHash ih = InfoHash.fromHashList(new byte[32]) + SharedFile sf1 = new SharedFile(new File("a b.c"), ih) + SharedFile sf2 = new SharedFile(new File("d e.f"), ih) + manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf1) + manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf2) + + UUID uuid = UUID.randomUUID() + SearchEvent se = new SearchEvent(searchHash: ih.getRoot(), uuid: uuid) + + manager.onSearchEvent(se) + + assert results != null + assert results.results.size() == 2 + assert results.results.contains(sf1) + assert results.results.contains(sf2) + assert results.uuid == uuid + } + + @Test + void testHash0Results() { + File f = new File("a b.c") + InfoHash ih = InfoHash.fromHashList(new byte[32]) + SharedFile sf = new SharedFile(f,ih) + FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) + manager.onFileHashedEvent(fhe) + + manager.onSearchEvent new SearchEvent(searchHash: new byte[32], uuid: UUID.randomUUID()) + + assert results == null + } + + @Test + void testKeyword1Result() { + File f = new File("a b.c") + InfoHash ih = InfoHash.fromHashList(new byte[32]) + SharedFile sf = new SharedFile(f,ih) + FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) + manager.onFileHashedEvent(fhe) + + UUID uuid = UUID.randomUUID() + manager.onSearchEvent new SearchEvent(searchTerms: ["a"], uuid:uuid) + + assert results != null + assert results.results.size() == 1 + assert results.results.contains(sf) + assert results.uuid == uuid + } + + @Test + void testKeyword2Results() { + File f1 = new File("a b.c") + InfoHash ih1 = InfoHash.fromHashList(new byte[32]) + SharedFile sf1 = new SharedFile(f1, ih1) + 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) + manager.onFileLoadedEvent new FileLoadedEvent(loadedFile: sf2) + + UUID uuid = UUID.randomUUID() + manager.onSearchEvent new SearchEvent(searchTerms: ["c"], uuid:uuid) + + assert results != null + assert results.results.size() == 2 + assert results.results.contains(sf1) + assert results.results.contains(sf2) + assert results.uuid == uuid + } + + @Test + void testKeyword0Results() { + File f = new File("a b.c") + InfoHash ih = InfoHash.fromHashList(new byte[32]) + SharedFile sf = new SharedFile(f,ih) + FileHashedEvent fhe = new FileHashedEvent(sharedFile: sf) + manager.onFileHashedEvent(fhe) + + manager.onSearchEvent new SearchEvent(searchTerms: ["d"], uuid: UUID.randomUUID()) + + assert results == null + } + + @Test + void testRemoveFileExistingHash() { + InfoHash ih = InfoHash.fromHashList(new byte[32]) + SharedFile sf1 = new SharedFile(new File("a b.c"), ih) + SharedFile sf2 = new SharedFile(new File("d e.f"), ih) + manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf1) + manager.onFileLoadedEvent new FileLoadedEvent(loadedFile : sf2) + + manager.onFileUnsharedEvent new FileUnsharedEvent(unsharedFile: sf2) + + manager.onSearchEvent new SearchEvent(searchHash : ih.getRoot()) + assert results != null + assert results.results.size() == 1 + assert results.results.contains(sf1) + } + + @Test + void testRemoveFile() { + File f1 = new File("a b.c") + InfoHash ih1 = InfoHash.fromHashList(new byte[32]) + SharedFile sf1 = new SharedFile(f1, ih1) + 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) + manager.onFileLoadedEvent new FileLoadedEvent(loadedFile: sf2) + + manager.onFileUnsharedEvent new FileUnsharedEvent(unsharedFile: sf2) + + // 1 match left + manager.onSearchEvent new SearchEvent(searchTerms: ["c"]) + assert results != null + assert results.results.size() == 1 + assert results.results.contains(sf1) + + // no match + results = null + manager.onSearchEvent new SearchEvent(searchTerms: ["d"]) + assert results == null + + } +}