Search in sources :

Example 6 with BloomFilter

use of com.biglybt.core.util.bloom.BloomFilter in project BiglyBT by BiglySoftware.

the class BloomFilterRotator method remove.

@Override
public int remove(byte[] value) {
    int res = 0;
    for (int i = 0; i < filters.length; i++) {
        BloomFilter filter = filters[i];
        int r = filter.remove(value);
        if (filter == current_filter) {
            res = r;
        }
    }
    return (res);
}
Also used : BloomFilter(com.biglybt.core.util.bloom.BloomFilter)

Example 7 with BloomFilter

use of com.biglybt.core.util.bloom.BloomFilter in project BiglyBT by BiglySoftware.

the class RelatedContentSearcher method harvestBlooms.

private void harvestBlooms() {
    harvest_dispatcher.dispatch(new AERunnable() {

        @Override
        public void runSupport() {
            if (harvest_dispatcher.getQueueSize() > 0) {
                return;
            }
            ForeignBloom oldest = null;
            synchronized (harvested_blooms) {
                for (ForeignBloom bloom : harvested_blooms.values()) {
                    if (oldest == null || bloom.getLastUpdateTime() < oldest.getLastUpdateTime()) {
                        oldest = bloom;
                    }
                }
            }
            long now = SystemTime.getMonotonousTime();
            if (oldest != null) {
                if (now - oldest.getLastUpdateTime() > HARVEST_BLOOM_UPDATE_MILLIS) {
                    DistributedDatabaseContact ddb_contact = oldest.getContact();
                    if (now - oldest.getCreateTime() > HARVEST_BLOOM_DISCARD_MILLIS && harvested_blooms.size() >= HARVEST_MAX_BLOOMS / 2) {
                        // don't want to stick with a stable one for too long otherwise the stabler
                        // nodes will end up in lots of other nodes' harvest set and receive
                        // undue attention (unless we don't have that many nodes...)
                        logSearch("Harvest: discarding " + ddb_contact.getAddress());
                        synchronized (harvested_blooms) {
                            harvested_blooms.remove(ddb_contact.getID());
                        }
                    } else {
                        BloomFilter updated_filter = sendRemoteUpdate(oldest);
                        if (updated_filter == null) {
                            synchronized (harvested_blooms) {
                                harvested_blooms.remove(ddb_contact.getID());
                                harvested_fails.put(ddb_contact.getID(), "");
                            }
                        } else {
                            oldest.updateFilter(updated_filter);
                        }
                    }
                }
            }
            if (harvested_blooms.size() < HARVEST_MAX_BLOOMS) {
                try {
                    int fail_count = 0;
                    DHTInterface[] dhts = dht_plugin.getDHTInterfaces();
                    outer: for (DHTInterface dht : dhts) {
                        if (dht.isIPV6()) {
                            continue;
                        }
                        int network = dht.getNetwork();
                        if (SEARCH_CVS_ONLY_DEFAULT && network != DHT.NW_AZ_CVS) {
                            logSearch("Harvest: ignoring main DHT");
                            continue;
                        }
                        DHTPluginContact[] contacts = dht.getReachableContacts();
                        byte[] dht_id = dht.getID();
                        for (DHTPluginContact contact : contacts) {
                            byte[] contact_id = contact.getID();
                            if (Arrays.equals(dht_id, contact_id)) {
                                continue;
                            }
                            DistributedDatabaseContact ddb_contact = importContact(contact, network);
                            synchronized (harvested_blooms) {
                                if (harvested_fails.containsKey(contact_id)) {
                                    continue;
                                }
                                if (harvested_blooms.containsKey(contact_id)) {
                                    continue;
                                }
                            }
                            BloomFilter filter = sendRemoteFetch(ddb_contact);
                            logSearch("harvest: " + contact.getString() + " -> " + (filter == null ? "null" : filter.getString()));
                            if (filter != null) {
                                synchronized (harvested_blooms) {
                                    harvested_blooms.put(contact_id, new ForeignBloom(ddb_contact, filter));
                                }
                                break outer;
                            } else {
                                synchronized (harvested_blooms) {
                                    harvested_fails.put(contact_id, "");
                                }
                                fail_count++;
                                if (fail_count > 5) {
                                    break outer;
                                }
                            }
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
            synchronized (harvested_blooms) {
                if (harvested_fails.size() > HARVEST_MAX_FAILS_HISTORY) {
                    harvested_fails.clear();
                }
            }
        }
    });
}
Also used : DHTInterface(com.biglybt.plugin.dht.DHTPluginInterface.DHTInterface) BloomFilter(com.biglybt.core.util.bloom.BloomFilter) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact)

Example 8 with BloomFilter

use of com.biglybt.core.util.bloom.BloomFilter in project BiglyBT by BiglySoftware.

the class RelatedContentSearcher method receiveRemoteRequest.

protected Map<String, Object> receiveRemoteRequest(DistributedDatabaseContact originator, Map<String, Object> request) {
    Map<String, Object> response = new HashMap<>();
    try {
        boolean originator_is_neighbour = false;
        DHTInterface[] dhts = dht_plugin.getDHTInterfaces();
        byte[] originator_id = originator.getID();
        byte[] originator_bytes = AddressUtils.getAddressBytes(originator.getAddress());
        for (DHTInterface d : dhts) {
            List<DHTPluginContact> contacts = d.getClosestContacts(d.getID(), true);
            for (DHTPluginContact c : contacts) {
                if (Arrays.equals(c.getID(), originator_id)) {
                    originator_is_neighbour = true;
                    break;
                }
            }
            if (originator_is_neighbour) {
                break;
            }
        }
        String req_type = MapUtils.getMapString(request, "x", null);
        if (req_type != null) {
            boolean dup = harvest_op_requester_bloom.contains(originator_bytes);
            logSearch("Received remote request: " + BDecoder.decodeStrings(request) + " from " + originator.getAddress() + "/" + originator.getNetwork() + ", dup=" + dup + ", bs=" + harvest_op_requester_bloom.getEntryCount());
            if (!dup) {
                harvest_op_requester_bloom.add(originator_bytes);
                if (req_type.equals("f")) {
                    BloomFilter filter = getKeyBloom(!originator_is_neighbour);
                    if (filter != null) {
                        response.put("f", filter.serialiseToMap());
                    }
                } else if (req_type.equals("u")) {
                    BloomFilter filter = getKeyBloom(!originator_is_neighbour);
                    if (filter != null) {
                        int existing_size = MapUtils.importInt(request, "s", 0);
                        if (existing_size != filter.getEntryCount()) {
                            response.put("f", filter.serialiseToMap());
                        } else {
                            response.put("s", new Long(existing_size));
                        }
                    }
                }
            }
        } else {
            // fallback to default handling
            int hits = harvest_se_requester_bloom.count(originator_bytes);
            String term = MapUtils.getMapString(request, "t", null);
            term = fixupTerm(term);
            String network = MapUtils.getMapString(request, "n", "");
            boolean search_cvs_only = network.equals("c");
            int min_seeds = MapUtils.importInt(request, "s", SEARCH_MIN_SEEDS_DEFAULT);
            int min_leechers = MapUtils.importInt(request, "l", SEARCH_MIN_LEECHERS_DEFAULT);
            // System.out.println( "Received remote search: '" + term + "' from " + originator.getAddress() + ", hits=" + hits + ", bs=" + harvest_se_requester_bloom.getEntryCount());
            logSearch("Received remote search: '" + term + "' from " + originator.getAddress() + ", hits=" + hits + ", bs=" + harvest_se_requester_bloom.getEntryCount());
            if (hits < 10) {
                harvest_se_requester_bloom.add(originator_bytes);
                if (term != null) {
                    List<RelatedContent> matches = matchContent(term, min_seeds, min_leechers, false, search_cvs_only);
                    List<Map<String, Object>> l_list = new ArrayList<>();
                    for (int i = 0; i < matches.size(); i++) {
                        RelatedContent c = matches.get(i);
                        Map<String, Object> map = new HashMap<>();
                        l_list.add(map);
                        MapUtils.exportLong(map, "v", c.getVersion());
                        MapUtils.setMapString(map, "n", c.getTitle());
                        MapUtils.exportLong(map, "s", c.getSize());
                        MapUtils.exportLong(map, "r", c.getRank());
                        MapUtils.exportLong(map, "d", c.getLastSeenSecs());
                        MapUtils.exportLong(map, "p", c.getPublishDate() / (60 * 60 * 1000));
                        MapUtils.exportLong(map, "l", c.getLeechers());
                        MapUtils.exportLong(map, "z", c.getSeeds());
                        byte[] hash = c.getHash();
                        if (hash != null) {
                            map.put("h", hash);
                        }
                        byte[] tracker_keys = c.getTrackerKeys();
                        if (tracker_keys != null) {
                            map.put("k", tracker_keys);
                        }
                        byte[] ws_keys = c.getWebSeedKeys();
                        if (ws_keys != null) {
                            map.put("w", ws_keys);
                        }
                        String[] tags = c.getTags();
                        if (tags != null) {
                            map.put("g", manager.encodeTags(tags));
                        }
                        byte nets = c.getNetworksInternal();
                        if (nets != RelatedContentManager.NET_NONE && nets != RelatedContentManager.NET_PUBLIC) {
                            map.put("o", new Long(nets & 0x00ff));
                        }
                    // don't bother with tracker as no use to caller really
                    }
                    response.put("l", l_list);
                    List<DistributedDatabaseContact> bloom_hits = searchForeignBlooms(term);
                    if (bloom_hits.size() > 0) {
                        List<Map> c_list = new ArrayList<>();
                        for (DistributedDatabaseContact c : bloom_hits) {
                            Map m = new HashMap();
                            c_list.add(m);
                            InetSocketAddress address = c.getAddress();
                            if (address.isUnresolved()) {
                                m.put("m", c.exportToMap());
                            } else {
                                m.put("a", address.getAddress().getHostAddress());
                                m.put("p", new Long(address.getPort()));
                            }
                        }
                        response.put("c", c_list);
                    }
                }
            }
        }
    } catch (Throwable e) {
    }
    return (response);
}
Also used : InetSocketAddress(java.net.InetSocketAddress) DHTInterface(com.biglybt.plugin.dht.DHTPluginInterface.DHTInterface) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact) BloomFilter(com.biglybt.core.util.bloom.BloomFilter)

Example 9 with BloomFilter

use of com.biglybt.core.util.bloom.BloomFilter in project BiglyBT by BiglySoftware.

the class RelatedContentSearcher method searchForeignBlooms.

List<DistributedDatabaseContact> searchForeignBlooms(String term) {
    boolean is_popularity = isPopularity(term);
    List<DistributedDatabaseContact> result = new ArrayList<>();
    try {
        String[] bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase());
        // note that we don't need to unescape tags in this process as tags are escaped when
        // inserted into the blooms and include the 'tag:' prefix
        int[] bit_types = new int[bits.length];
        byte[][] bit_bytes = new byte[bit_types.length][];
        byte[][][] extras = new byte[bit_types.length][][];
        for (int i = 0; i < bits.length; i++) {
            String bit = bits[i].trim();
            if (bit.length() > 0) {
                char c = bit.charAt(0);
                if (c == '+') {
                    bit_types[i] = 1;
                    bit = bit.substring(1);
                } else if (c == '-') {
                    bit_types[i] = 2;
                    bit = bit.substring(1);
                }
                if (bit.startsWith("(") && bit.endsWith((")"))) {
                    // ignore
                    bit_types[i] = 3;
                } else if (bit.contains("|")) {
                    String[] parts = bit.split("\\|");
                    List<String> p = new ArrayList<>();
                    for (String part : parts) {
                        part = part.trim();
                        if (part.length() > 0) {
                            p.add(part);
                        }
                    }
                    if (p.size() == 0) {
                        bit_types[i] = 3;
                    } else {
                        bit_types[i] = 4;
                        extras[i] = new byte[p.size()][];
                        for (int j = 0; j < p.size(); j++) {
                            extras[i][j] = p.get(j).getBytes("UTF8");
                        }
                    }
                }
                bit_bytes[i] = bit.getBytes("UTF8");
            }
        }
        synchronized (harvested_blooms) {
            for (ForeignBloom fb : harvested_blooms.values()) {
                if (is_popularity) {
                    result.add(fb.getContact());
                } else {
                    BloomFilter filter = fb.getFilter();
                    boolean failed = false;
                    int matches = 0;
                    for (int i = 0; i < bit_bytes.length; i++) {
                        byte[] bit = bit_bytes[i];
                        if (bit == null || bit.length == 0) {
                            continue;
                        }
                        int type = bit_types[i];
                        if (type == 3) {
                            continue;
                        }
                        if (type == 0 || type == 1) {
                            if (filter.contains(bit)) {
                                matches++;
                            } else {
                                failed = true;
                                break;
                            }
                        } else if (type == 2) {
                            if (!filter.contains(bit)) {
                                matches++;
                            } else {
                                failed = true;
                                break;
                            }
                        } else if (type == 4) {
                            byte[][] parts = extras[i];
                            int old_matches = matches;
                            for (byte[] p : parts) {
                                if (filter.contains(p)) {
                                    matches++;
                                    break;
                                }
                            }
                            if (matches == old_matches) {
                                failed = true;
                                break;
                            }
                        }
                    }
                    if (matches > 0 && !failed) {
                        result.add(fb.getContact());
                    }
                }
            }
        }
    } catch (UnsupportedEncodingException e) {
        Debug.out(e);
    }
    return (result);
}
Also used : UnsupportedEncodingException(java.io.UnsupportedEncodingException) BloomFilter(com.biglybt.core.util.bloom.BloomFilter)

Example 10 with BloomFilter

use of com.biglybt.core.util.bloom.BloomFilter in project BiglyBT by BiglySoftware.

the class RelatedContentSearcher method testKeyBloom.

private void testKeyBloom() {
    if (true) {
        return;
    }
    System.out.println("test key bloom");
    try {
        Map<String, int[]> all_words = new HashMap<>();
        synchronized (manager.rcm_lock) {
            ContentCache cache = manager.loadRelatedContent();
            List<DownloadInfo> dht_infos = getDHTInfos(false);
            Iterator<DownloadInfo> it_dht = dht_infos.iterator();
            Iterator<DownloadInfo> it_transient = RelatedContentManager.transient_info_cache.values().iterator();
            Iterator<DownloadInfo> it_rc = cache.related_content.values().iterator();
            updateKeyBloom(cache);
            int i = 0;
            for (Iterator _it : new Iterator[] { it_transient, it_rc, it_dht }) {
                Iterator<DownloadInfo> it = (Iterator<DownloadInfo>) _it;
                while (it.hasNext()) {
                    DownloadInfo di = it.next();
                    List<String> words = getDHTWords(di);
                    for (String word : words) {
                        int[] x = all_words.get(word);
                        if (x == null) {
                            x = new int[3];
                            all_words.put(word, x);
                        }
                        x[i] = 1;
                    }
                }
                i++;
            }
        }
        BloomFilter bloom = getKeyBloom(true);
        int total = 0;
        int clashes = 0;
        int misses = 0;
        int match_fails = 0;
        Random random = new Random();
        for (Map.Entry<String, int[]> entry : all_words.entrySet()) {
            String word = entry.getKey();
            int[] source = entry.getValue();
            boolean r1 = bloom.contains(word.getBytes("UTF-8"));
            boolean r2 = bloom.contains((word + random.nextLong()).getBytes("UTF-8"));
            System.out.println(word + " -> " + r1 + "/" + r2);
            total++;
            if (r1 && r2) {
                clashes++;
            }
            if (!r1) {
                misses++;
            }
            List<RelatedContent> hits = matchContent(word, SEARCH_MIN_SEEDS_DEFAULT, SEARCH_MIN_LEECHERS_DEFAULT, true, false);
            if (hits.size() == 0) {
                hits = matchContent(word, SEARCH_MIN_SEEDS_DEFAULT, SEARCH_MIN_LEECHERS_DEFAULT, true, false);
                match_fails++;
            }
        }
        System.out.println("total=" + total + ", clash=" + clashes + ", miss=" + misses + ", fails=" + match_fails + ", bloom=" + bloom.getString());
    } catch (Throwable e) {
        e.printStackTrace();
    }
}
Also used : ContentCache(com.biglybt.core.content.RelatedContentManager.ContentCache) BloomFilter(com.biglybt.core.util.bloom.BloomFilter) DownloadInfo(com.biglybt.core.content.RelatedContentManager.DownloadInfo)

Aggregations

BloomFilter (com.biglybt.core.util.bloom.BloomFilter)17 DownloadInfo (com.biglybt.core.content.RelatedContentManager.DownloadInfo)2 DHTTransportContact (com.biglybt.core.dht.transport.DHTTransportContact)2 DHTPluginContact (com.biglybt.plugin.dht.DHTPluginContact)2 DHTInterface (com.biglybt.plugin.dht.DHTPluginInterface.DHTInterface)2 ContentCache (com.biglybt.core.content.RelatedContentManager.ContentCache)1 LogEvent (com.biglybt.core.logging.LogEvent)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 InetSocketAddress (java.net.InetSocketAddress)1 Signature (java.security.Signature)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Random (java.util.Random)1