Search in sources :

Example 1 with DHTPluginContact

use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.

the class DHTTrackerPlugin method processNonRegistrations.

protected void processNonRegistrations() {
    Download ready_download = null;
    long ready_download_next_check = -1;
    long now = plugin_interface.getUtilities().getCurrentSystemTime();
    // unfortunately getting scrape results can acquire locks and there is a vague
    // possibility of deadlock here, so pre-fetch the scrape results
    List<Download> to_scrape = new ArrayList<>();
    try {
        this_mon.enter();
        Iterator<Download> it = interesting_downloads.keySet().iterator();
        while (it.hasNext() && ready_download == null) {
            Download download = it.next();
            Torrent torrent = download.getTorrent();
            if (torrent == null) {
                continue;
            }
            int[] run_data = running_downloads.get(download);
            if (run_data == null || run_data[0] == REG_TYPE_DERIVED) {
                // looks like we'll need the scrape below
                to_scrape.add(download);
            }
        }
    } finally {
        this_mon.exit();
    }
    Map<Download, DownloadScrapeResult> scrapes = new HashMap<>();
    for (int i = 0; i < to_scrape.size(); i++) {
        Download download = (Download) to_scrape.get(i);
        scrapes.put(download, download.getLastScrapeResult());
    }
    try {
        this_mon.enter();
        Iterator<Download> it = interesting_downloads.keySet().iterator();
        while (it.hasNext() && ready_download == null) {
            Download download = it.next();
            Torrent torrent = download.getTorrent();
            if (torrent == null) {
                continue;
            }
            int[] run_data = running_downloads.get(download);
            if (run_data == null || run_data[0] == REG_TYPE_DERIVED) {
                boolean force = torrent.wasCreatedByUs();
                if (!force) {
                    if (interesting_pub_max > 0 && interesting_published > interesting_pub_max) {
                        continue;
                    }
                    DownloadScrapeResult scrape = (DownloadScrapeResult) scrapes.get(download);
                    if (scrape == null) {
                        continue;
                    }
                    if (scrape.getSeedCount() + scrape.getNonSeedCount() > NUM_WANT) {
                        continue;
                    }
                }
                long target = ((Long) interesting_downloads.get(download)).longValue();
                long check_period = TorrentUtils.isDecentralised(torrent.getAnnounceURL()) ? INTERESTING_DHT_CHECK_PERIOD : INTERESTING_CHECK_PERIOD;
                if (target <= now) {
                    ready_download = download;
                    ready_download_next_check = now + check_period;
                    interesting_downloads.put(download, new Long(ready_download_next_check));
                } else if (target - now > check_period) {
                    interesting_downloads.put(download, new Long(now + (target % check_period)));
                }
            }
        }
    } finally {
        this_mon.exit();
    }
    if (ready_download != null) {
        final Download f_ready_download = ready_download;
        final Torrent torrent = ready_download.getTorrent();
        if (ready_download.getFlag(Download.FLAG_METADATA_DOWNLOAD)) {
            try {
                this_mon.enter();
                interesting_downloads.remove(f_ready_download);
            } finally {
                this_mon.exit();
            }
        } else if (dht.isDiversified(torrent.getHash())) {
            try {
                this_mon.enter();
                interesting_downloads.remove(f_ready_download);
            } finally {
                this_mon.exit();
            }
        } else {
            // System.out.println( "presence query for " + ready_download.getName());
            final long start = now;
            final long f_next_check = ready_download_next_check;
            dht.get(torrent.getHash(), "Presence query for '" + ready_download.getName() + "'", (byte) 0, INTERESTING_AVAIL_MAX, ANNOUNCE_TIMEOUT, false, false, new DHTPluginOperationListener() {

                private boolean diversified;

                private int leechers = 0;

                private int seeds = 0;

                private int i2p_leechers = 0;

                private int i2p_seeds = 0;

                @Override
                public boolean diversified() {
                    diversified = true;
                    return (false);
                }

                @Override
                public void starts(byte[] key) {
                }

                @Override
                public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
                    boolean is_leecher = (value.getFlags() & DHTPlugin.FLAG_DOWNLOADING) == 1;
                    if (is_leecher) {
                        leechers++;
                    } else {
                        seeds++;
                    }
                    try {
                        String[] tokens = new String(value.getValue()).split(";");
                        for (int i = 1; i < tokens.length; i++) {
                            String token = tokens[i].trim();
                            if (token.length() > 0) {
                                if (!Character.isDigit(token.charAt(0))) {
                                    String flag_str = token;
                                    if (flag_str.contains("I")) {
                                        if (is_leecher) {
                                            i2p_leechers++;
                                        } else {
                                            i2p_seeds++;
                                        }
                                    }
                                }
                            }
                        }
                    } catch (Throwable e) {
                    }
                }

                @Override
                public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
                }

                @Override
                public void complete(byte[] key, boolean timeout_occurred) {
                    // System.out.println( "    presence query for " + f_ready_download.getName() + "->" + total + "/div = " + diversified );
                    int total = leechers + seeds;
                    log(torrent, "Presence query: availability=" + (total == INTERESTING_AVAIL_MAX ? (INTERESTING_AVAIL_MAX + "+") : (total + "")) + ",div=" + diversified + " (elapsed=" + TimeFormatter.formatColonMillis(SystemTime.getCurrentTime() - start) + ")");
                    if (diversified) {
                        try {
                            this_mon.enter();
                            interesting_downloads.remove(f_ready_download);
                        } finally {
                            this_mon.exit();
                        }
                    } else if (total < INTERESTING_AVAIL_MAX) {
                        try {
                            this_mon.enter();
                            interesting_downloads.remove(f_ready_download);
                        } finally {
                            this_mon.exit();
                        }
                        interesting_published++;
                        if (!disable_put) {
                            dht.put(torrent.getHash(), "Presence store '" + f_ready_download.getName() + "'", // port 0, no connections
                            "0".getBytes(), (byte) 0, new DHTPluginOperationListener() {

                                @Override
                                public boolean diversified() {
                                    return (true);
                                }

                                @Override
                                public void starts(byte[] key) {
                                }

                                @Override
                                public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
                                }

                                @Override
                                public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
                                }

                                @Override
                                public void complete(byte[] key, boolean timeout_occurred) {
                                }
                            });
                        }
                    }
                    try {
                        this_mon.enter();
                        int[] run_data = running_downloads.get(f_ready_download);
                        if (run_data == null) {
                            run_data = run_data_cache.get(f_ready_download);
                        }
                        if (run_data != null) {
                            if (total < INTERESTING_AVAIL_MAX) {
                                run_data[1] = seeds;
                                run_data[2] = leechers;
                                run_data[3] = total;
                            } else {
                                run_data[1] = Math.max(run_data[1], seeds);
                                run_data[2] = Math.max(run_data[2], leechers);
                            }
                            run_data[4] = (int) (SystemTime.getCurrentTime() / 1000);
                        }
                    } finally {
                        this_mon.exit();
                    }
                    if (i2p_seeds + i2p_leechers > 0) {
                        int[] details = (int[]) f_ready_download.getUserData(DOWNLOAD_USER_DATA_I2P_SCRAPE_KEY);
                        if (details == null) {
                            details = new int[] { i2p_seeds, i2p_leechers };
                            f_ready_download.setUserData(DOWNLOAD_USER_DATA_I2P_SCRAPE_KEY, details);
                        } else {
                            details[0] = Math.max(details[0], i2p_seeds);
                            details[1] = Math.max(details[1], i2p_leechers);
                        }
                    }
                    f_ready_download.setScrapeResult(new DownloadScrapeResult() {

                        @Override
                        public Download getDownload() {
                            return (null);
                        }

                        @Override
                        public int getResponseType() {
                            return (DownloadScrapeResult.RT_SUCCESS);
                        }

                        @Override
                        public int getSeedCount() {
                            return (seeds);
                        }

                        @Override
                        public int getNonSeedCount() {
                            return (leechers);
                        }

                        @Override
                        public long getScrapeStartTime() {
                            return (SystemTime.getCurrentTime());
                        }

                        @Override
                        public void setNextScrapeStartTime(long nextScrapeStartTime) {
                        }

                        @Override
                        public long getNextScrapeStartTime() {
                            return (f_next_check);
                        }

                        @Override
                        public String getStatus() {
                            return ("OK");
                        }

                        @Override
                        public URL getURL() {
                            URL url_to_report = torrent.isDecentralised() ? torrent.getAnnounceURL() : DEFAULT_URL;
                            return (url_to_report);
                        }
                    });
                }
            });
        }
    }
}
Also used : DHTPluginValue(com.biglybt.plugin.dht.DHTPluginValue) Torrent(com.biglybt.pif.torrent.Torrent) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact) URL(java.net.URL) DHTPluginOperationListener(com.biglybt.plugin.dht.DHTPluginOperationListener)

Example 2 with DHTPluginContact

use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.

the class DHTTrackerPlugin method trackerRemove.

protected void trackerRemove(final Download download, final trackerTarget target) {
    if (disable_put) {
        return;
    }
    if (download.getFlag(Download.FLAG_METADATA_DOWNLOAD)) {
        return;
    }
    final long start = SystemTime.getCurrentTime();
    if (dht.hasLocalKey(target.getHash())) {
        increaseActive(download);
        dht.remove(target.getHash(), "Tracker dereg of '" + download.getName() + "'" + target.getDesc(), new DHTPluginOperationListener() {

            @Override
            public boolean diversified() {
                return (true);
            }

            @Override
            public void starts(byte[] key) {
            }

            @Override
            public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
            }

            @Override
            public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
            }

            @Override
            public void complete(byte[] key, boolean timeout_occurred) {
                if (target.getType() == REG_TYPE_FULL) {
                    log(download, "Unregistration of '" + target.getDesc() + "' completed (elapsed=" + TimeFormatter.formatColonMillis(SystemTime.getCurrentTime() - start) + ")");
                }
                decreaseActive(download);
            }
        });
    }
}
Also used : DHTPluginValue(com.biglybt.plugin.dht.DHTPluginValue) DHTPluginOperationListener(com.biglybt.plugin.dht.DHTPluginOperationListener) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact)

Example 3 with DHTPluginContact

use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.

the class DHTTrackerPlugin method scrape.

/**
 * This is used by the dhtscraper plugin
 */
public DownloadScrapeResult scrape(byte[] hash) {
    final int[] seeds = { 0 };
    final int[] leechers = { 0 };
    final AESemaphore sem = new AESemaphore("DHTTrackerPlugin:scrape");
    dht.get(hash, "Scrape for " + ByteFormatter.encodeString(hash).substring(0, 16), DHTPlugin.FLAG_DOWNLOADING, NUM_WANT, SCRAPE_TIMEOUT, false, false, new DHTPluginOperationListener() {

        @Override
        public boolean diversified() {
            return (true);
        }

        @Override
        public void starts(byte[] key) {
        }

        @Override
        public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
            if ((value.getFlags() & DHTPlugin.FLAG_DOWNLOADING) == 1) {
                leechers[0]++;
            } else {
                seeds[0]++;
            }
        }

        @Override
        public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
        }

        @Override
        public void complete(byte[] key, boolean timeout_occurred) {
            sem.release();
        }
    });
    sem.reserve();
    return (new DownloadScrapeResult() {

        @Override
        public Download getDownload() {
            return (null);
        }

        @Override
        public int getResponseType() {
            return (DownloadScrapeResult.RT_SUCCESS);
        }

        @Override
        public int getSeedCount() {
            return (seeds[0]);
        }

        @Override
        public int getNonSeedCount() {
            return (leechers[0]);
        }

        @Override
        public long getScrapeStartTime() {
            return (0);
        }

        @Override
        public void setNextScrapeStartTime(long nextScrapeStartTime) {
        }

        @Override
        public long getNextScrapeStartTime() {
            return (0);
        }

        @Override
        public String getStatus() {
            return ("OK");
        }

        @Override
        public URL getURL() {
            return (null);
        }
    });
}
Also used : DHTPluginValue(com.biglybt.plugin.dht.DHTPluginValue) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact) URL(java.net.URL) DHTPluginOperationListener(com.biglybt.plugin.dht.DHTPluginOperationListener)

Example 4 with DHTPluginContact

use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.

the class DHTTrackerPlugin method trackerPut.

protected void trackerPut(final Download download, RegistrationDetails details) {
    final long start = SystemTime.getCurrentTime();
    trackerTarget[] targets = details.getTargets(true);
    byte flags = details.getFlags();
    for (int i = 0; i < targets.length; i++) {
        final trackerTarget target = targets[i];
        int target_type = target.getType();
        // don't let a put block an announce as we don't want to be waiting for
        // this at start of day to get a torrent running
        // increaseActive( dl );
        String encoded = details.getPutDetails().getEncoded();
        byte[] encoded_bytes = encoded.getBytes();
        DHTPluginValue existing = dht.getLocalValue(target.getHash());
        if (existing != null && existing.getFlags() == flags && Arrays.equals(existing.getValue(), encoded_bytes)) {
            continue;
        }
        if (disable_put) {
            if (target_type == REG_TYPE_FULL) {
                log(download, "Registration of '" + target.getDesc() + "' skipped as disabled due to use of SOCKS proxy");
            }
        } else if (download.getFlag(Download.FLAG_METADATA_DOWNLOAD)) {
            log(download, "Registration of '" + target.getDesc() + "' skipped as metadata download");
        } else if (target_type == REG_TYPE_DERIVED && dht.isSleeping()) {
            log(download, "Registration of '" + target.getDesc() + "' skipped as sleeping");
        } else {
            dht.put(target.getHash(), "Tracker reg of '" + download.getName() + "'" + target.getDesc() + " -> " + encoded, encoded_bytes, flags, false, new DHTPluginOperationListener() {

                @Override
                public boolean diversified() {
                    return (true);
                }

                @Override
                public void starts(byte[] key) {
                }

                @Override
                public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
                }

                @Override
                public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
                }

                @Override
                public void complete(byte[] key, boolean timeout_occurred) {
                    if (target.getType() == REG_TYPE_FULL) {
                        log(download, "Registration of '" + target.getDesc() + "' completed (elapsed=" + TimeFormatter.formatColonMillis((SystemTime.getCurrentTime() - start)) + ")");
                    }
                // decreaseActive( dl );
                }
            });
        }
    }
}
Also used : DHTPluginValue(com.biglybt.plugin.dht.DHTPluginValue) DHTPluginOperationListener(com.biglybt.plugin.dht.DHTPluginOperationListener) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact)

Example 5 with DHTPluginContact

use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.

the class RelatedContentSearcher method searchRCM.

protected SearchInstance searchRCM(Map<String, Object> search_parameters, SearchObserver _observer) throws SearchException {
    final String term = fixupTerm((String) search_parameters.get(SearchProvider.SP_SEARCH_TERM));
    final boolean is_popular = isPopularity(term);
    final int min_seeds = MapUtils.importInt(search_parameters, SearchProvider.SP_MIN_SEEDS, is_popular ? SEARCH_POP_MIN_SEEDS_DEFAULT : SEARCH_MIN_SEEDS_DEFAULT);
    final int min_leechers = MapUtils.importInt(search_parameters, SearchProvider.SP_MIN_LEECHERS, is_popular ? SEARCH_POP_MIN_LEECHERS_DEFAULT : SEARCH_MIN_LEECHERS_DEFAULT);
    final MySearchObserver observer = new MySearchObserver(_observer, min_seeds, min_leechers);
    final SearchInstance si = new SearchInstance() {

        @Override
        public void cancel() {
            Debug.out("Cancelled");
        }
    };
    if (term == null) {
        observer.complete();
    } else {
        new AEThread2("RCM:search", true) {

            @Override
            public void run() {
                boolean search_cvs_only = SEARCH_CVS_ONLY_DEFAULT;
                final Set<String> hashes_sync_me = new HashSet<>();
                try {
                    List<RelatedContent> matches = matchContent(term, min_seeds, min_leechers, true, search_cvs_only);
                    for (final RelatedContent c : matches) {
                        final byte[] hash = c.getHash();
                        if (hash == null) {
                            continue;
                        }
                        hashes_sync_me.add(Base32.encode(hash));
                        SearchResult result = new SearchResult() {

                            @Override
                            public Object getProperty(int property_name) {
                                if (property_name == SearchResult.PR_VERSION) {
                                    return (new Long(c.getVersion()));
                                } else if (property_name == SearchResult.PR_NAME) {
                                    return (c.getTitle());
                                } else if (property_name == SearchResult.PR_SIZE) {
                                    return (c.getSize());
                                } else if (property_name == SearchResult.PR_HASH) {
                                    return (hash);
                                } else if (property_name == SearchResult.PR_RANK) {
                                    return (new Long(c.getRank() / 4));
                                } else if (property_name == SearchResult.PR_SEED_COUNT) {
                                    return (new Long(c.getSeeds()));
                                } else if (property_name == SearchResult.PR_LEECHER_COUNT) {
                                    return (new Long(c.getLeechers()));
                                } else if (property_name == SearchResult.PR_SUPER_SEED_COUNT) {
                                    return (new Long(0));
                                } else if (property_name == SearchResult.PR_PUB_DATE) {
                                    long date = c.getPublishDate();
                                    if (date <= 0) {
                                        return (null);
                                    }
                                    return (new Date(date));
                                } else if (property_name == SearchResult.PR_TORRENT_LINK || property_name == SearchResult.PR_DOWNLOAD_LINK || property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK) {
                                    byte[] hash = c.getHash();
                                    if (hash != null) {
                                        return (UrlUtils.getMagnetURI(hash, c.getTitle(), c.getNetworks()));
                                    }
                                } else if (property_name == SearchResult.PR_CATEGORY) {
                                    String[] tags = c.getTags();
                                    if (tags != null) {
                                        for (String tag : tags) {
                                            if (!tag.startsWith("_")) {
                                                return (tag);
                                            }
                                        }
                                    }
                                } else if (property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_TRACKER_KEYS) {
                                    return (c.getTrackerKeys());
                                } else if (property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_WEB_SEED_KEYS) {
                                    return (c.getWebSeedKeys());
                                } else if (property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_TAGS) {
                                    return (c.getTags());
                                } else if (property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_NETWORKS) {
                                    return (c.getNetworks());
                                }
                                return (null);
                            }
                        };
                        observer.resultReceived(si, result);
                    }
                } finally {
                    try {
                        final List<DistributedDatabaseContact> initial_hinted_contacts = searchForeignBlooms(term);
                        final Set<DistributedDatabaseContact> extra_hinted_contacts = new HashSet<>();
                        Collections.shuffle(initial_hinted_contacts);
                        // test injection of local
                        // hinted_contacts.add( 0, ddb.getLocalContact());
                        final LinkedList<DistributedDatabaseContact> contacts_to_search = new LinkedList<>();
                        final Map<InetSocketAddress, DistributedDatabaseContact> contact_map = new HashMap<>();
                        for (DistributedDatabaseContact c : initial_hinted_contacts) {
                            // stick in map so non-hinted get removed below, but interleave later
                            contact_map.put(c.getAddress(), c);
                        }
                        if (ddb != null) {
                            DHTInterface[] dhts = dht_plugin.getDHTInterfaces();
                            boolean public_dht = dht_plugin.getNetwork() == AENetworkClassifier.AT_PUBLIC;
                            for (DHTInterface dht : dhts) {
                                if (dht.isIPV6()) {
                                    continue;
                                }
                                int network = dht.getNetwork();
                                if (public_dht && search_cvs_only && network != DHT.NW_AZ_CVS) {
                                    logSearch("Search: ignoring main DHT");
                                    continue;
                                }
                                DHTPluginContact[] contacts = dht.getReachableContacts();
                                Collections.shuffle(Arrays.asList(contacts));
                                for (DHTPluginContact dc : contacts) {
                                    InetSocketAddress address = dc.getAddress();
                                    if (!contact_map.containsKey(address)) {
                                        try {
                                            DistributedDatabaseContact c = importContact(dc, network);
                                            contact_map.put(address, c);
                                            contacts_to_search.add(c);
                                        } catch (Throwable e) {
                                        }
                                    }
                                }
                            }
                            if (contact_map.size() < MAX_REMOTE_SEARCH_CONTACTS) {
                                for (DHTInterface dht : dhts) {
                                    if (dht.isIPV6()) {
                                        continue;
                                    }
                                    int network = dht.getNetwork();
                                    if (public_dht && search_cvs_only && network != DHT.NW_AZ_CVS) {
                                        logSearch("Search: ignoring main DHT");
                                        continue;
                                    }
                                    DHTPluginContact[] contacts = dht.getRecentContacts();
                                    for (DHTPluginContact dc : contacts) {
                                        InetSocketAddress address = dc.getAddress();
                                        if (!contact_map.containsKey(address)) {
                                            try {
                                                DistributedDatabaseContact c = importContact(dc, network);
                                                contact_map.put(address, c);
                                                contacts_to_search.add(c);
                                                if (contact_map.size() >= MAX_REMOTE_SEARCH_CONTACTS) {
                                                    break;
                                                }
                                            } catch (Throwable e) {
                                            }
                                        }
                                    }
                                    if (contact_map.size() >= MAX_REMOTE_SEARCH_CONTACTS) {
                                        break;
                                    }
                                }
                            }
                        }
                        // interleave hinted ones so we get some variety
                        int desired_pos = 0;
                        for (DistributedDatabaseContact dc : initial_hinted_contacts) {
                            if (desired_pos < contacts_to_search.size()) {
                                contacts_to_search.add(desired_pos, dc);
                                desired_pos += 2;
                            } else {
                                contacts_to_search.addLast(dc);
                            }
                        }
                        long start = SystemTime.getMonotonousTime();
                        long max = MAX_REMOTE_SEARCH_MILLIS;
                        final AESemaphore sem = new AESemaphore("RCM:rems");
                        int sent = 0;
                        final int[] done = { 0 };
                        logSearch("Search starts: contacts=" + contacts_to_search.size() + ", hinted=" + initial_hinted_contacts.size());
                        while (true) {
                            if (observer.getResultCount() >= 200 || SystemTime.getMonotonousTime() - start >= max) {
                                logSearch("Hard limit exceeded");
                                return;
                            }
                            if (sent >= MAX_REMOTE_SEARCH_CONTACTS) {
                                logSearch("Max contacts searched");
                                break;
                            }
                            final DistributedDatabaseContact contact_to_search;
                            synchronized (contacts_to_search) {
                                if (contacts_to_search.isEmpty()) {
                                    logSearch("Contacts exhausted");
                                    break;
                                } else {
                                    contact_to_search = contacts_to_search.removeFirst();
                                }
                            }
                            new AEThread2("RCM:rems", true) {

                                @Override
                                public void run() {
                                    try {
                                        logSearch("Searching " + contact_to_search.getAddress());
                                        List<DistributedDatabaseContact> extra_contacts = sendRemoteSearch(si, hashes_sync_me, contact_to_search, term, min_seeds, min_leechers, observer);
                                        if (extra_contacts == null) {
                                            logSearch("    " + contact_to_search.getAddress() + " failed");
                                            foreignBloomFailed(contact_to_search);
                                        } else {
                                            String type;
                                            if (initial_hinted_contacts.contains(contact_to_search)) {
                                                type = "i";
                                            } else if (extra_hinted_contacts.contains(contact_to_search)) {
                                                type = "e";
                                            } else {
                                                type = "n";
                                            }
                                            logSearch("    " + contact_to_search.getAddress() + " OK " + type + " - additional=" + extra_contacts.size());
                                            synchronized (contacts_to_search) {
                                                int insert_point = 0;
                                                if (type.equals("i")) {
                                                    for (int i = 0; i < contacts_to_search.size(); i++) {
                                                        if (extra_hinted_contacts.contains(contacts_to_search.get(i))) {
                                                            insert_point = i + 1;
                                                        }
                                                    }
                                                }
                                                for (DistributedDatabaseContact c : extra_contacts) {
                                                    InetSocketAddress address = c.getAddress();
                                                    if (!contact_map.containsKey(address)) {
                                                        logSearch("        additional target: " + address);
                                                        extra_hinted_contacts.add(c);
                                                        contact_map.put(address, c);
                                                        contacts_to_search.add(insert_point, c);
                                                    }
                                                }
                                            }
                                        }
                                    } finally {
                                        synchronized (done) {
                                            done[0]++;
                                        }
                                        sem.release();
                                    }
                                }
                            }.start();
                            sent++;
                            synchronized (done) {
                                if (done[0] >= MAX_REMOTE_SEARCH_CONTACTS / 2) {
                                    logSearch("Switching to reduced time limit (1)");
                                    // give another 5 secs for results to come in
                                    start = SystemTime.getMonotonousTime();
                                    max = REDUCED_REMOTE_SEARCH_MILLIS;
                                    break;
                                }
                            }
                            if (sent > 10) {
                                try {
                                    Thread.sleep(250);
                                } catch (Throwable e) {
                                }
                            }
                        }
                        logSearch("Request dispatch complete: sent=" + sent + ", done=" + done[0]);
                        for (int i = 0; i < sent; i++) {
                            if (done[0] > sent * 9 / 10) {
                                logSearch("9/10ths replied (" + done[0] + "/" + sent + "), done");
                                break;
                            }
                            long remaining = (start + max) - SystemTime.getMonotonousTime();
                            if (remaining > REDUCED_REMOTE_SEARCH_MILLIS && done[0] >= MAX_REMOTE_SEARCH_CONTACTS / 2) {
                                logSearch("Switching to reduced time limit (2)");
                                // give another 5 secs for results to come in
                                start = SystemTime.getMonotonousTime();
                                max = REDUCED_REMOTE_SEARCH_MILLIS;
                            }
                            if (remaining > 0) {
                                sem.reserve(250);
                            } else {
                                logSearch("Time exhausted");
                                break;
                            }
                        }
                    } finally {
                        logSearch("Search complete");
                        observer.complete();
                    }
                }
            }
        }.start();
    }
    return (si);
}
Also used : InetSocketAddress(java.net.InetSocketAddress) DHTInterface(com.biglybt.plugin.dht.DHTPluginInterface.DHTInterface) DHTPluginContact(com.biglybt.plugin.dht.DHTPluginContact)

Aggregations

DHTPluginContact (com.biglybt.plugin.dht.DHTPluginContact)10 DHTPluginOperationListener (com.biglybt.plugin.dht.DHTPluginOperationListener)7 DHTPluginValue (com.biglybt.plugin.dht.DHTPluginValue)7 InetSocketAddress (java.net.InetSocketAddress)4 DHTInterface (com.biglybt.plugin.dht.DHTPluginInterface.DHTInterface)3 URL (java.net.URL)3 BloomFilter (com.biglybt.core.util.bloom.BloomFilter)2 Torrent (com.biglybt.pif.torrent.Torrent)2 PEPeerManager (com.biglybt.core.peer.PEPeerManager)1 TrackerPeerSource (com.biglybt.core.tracker.TrackerPeerSource)1 TrackerPeerSourceAdapter (com.biglybt.core.tracker.TrackerPeerSourceAdapter)1 Peer (com.biglybt.pif.peers.Peer)1 PeerManager (com.biglybt.pif.peers.PeerManager)1