use of com.biglybt.plugin.dht.DHTPluginContact 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();
}
}
}
});
}
use of com.biglybt.plugin.dht.DHTPluginContact 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);
}
use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.
the class DHTTrackerPlugin method trackerRemove.
protected void trackerRemove(final Download download, RegistrationDetails details) {
if (disable_put) {
return;
}
if (download.getFlag(Download.FLAG_METADATA_DOWNLOAD)) {
return;
}
final long start = SystemTime.getCurrentTime();
trackerTarget[] targets = details.getTargets(true);
for (int i = 0; i < targets.length; i++) {
final trackerTarget target = targets[i];
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);
}
});
}
}
}
use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.
the class DHTTrackerPlugin method getTrackerPeerSources.
public TrackerPeerSource[] getTrackerPeerSources(final Torrent torrent) {
TrackerPeerSource vuze_dht = new TrackerPeerSourceAdapter() {
private volatile boolean query_done;
private volatile int status = TrackerPeerSource.ST_INITIALISING;
private volatile int seeds = 0;
private volatile int leechers = 0;
private void fixup() {
if (initialised_sem.isReleasedForever()) {
synchronized (this) {
if (query_done) {
return;
}
query_done = true;
status = TrackerPeerSource.ST_UPDATING;
}
dht.get(torrent.getHash(), "Availability lookup for '" + torrent.getName() + "'", DHTPlugin.FLAG_DOWNLOADING, NUM_WANT, ANNOUNCE_DERIVED_TIMEOUT, false, true, new DHTPluginOperationListener() {
@Override
public void starts(byte[] key) {
}
@Override
public boolean diversified() {
return (true);
}
@Override
public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
if ((value.getFlags() & DHTPlugin.FLAG_DOWNLOADING) == 1) {
seeds++;
} else {
leechers++;
}
}
@Override
public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
}
@Override
public void complete(byte[] key, boolean timeout_occurred) {
status = TrackerPeerSource.ST_ONLINE;
}
});
}
}
@Override
public int getType() {
return (TrackerPeerSource.TP_DHT);
}
@Override
public String getName() {
return ("Vuze DHT");
}
@Override
public int getStatus() {
fixup();
return (status);
}
@Override
public int getSeedCount() {
fixup();
int result = seeds;
if (result == 0 && status != TrackerPeerSource.ST_ONLINE) {
return (-1);
}
return (result);
}
@Override
public int getLeecherCount() {
fixup();
int result = leechers;
if (result == 0 && status != TrackerPeerSource.ST_ONLINE) {
return (-1);
}
return (result);
}
@Override
public int getPeers() {
return (-1);
}
@Override
public boolean isUpdating() {
return (status == TrackerPeerSource.ST_UPDATING);
}
};
if (alt_lookup_handler != null) {
TrackerPeerSource alt_dht = new TrackerPeerSourceAdapter() {
private volatile int status = TrackerPeerSource.ST_UPDATING;
private volatile int peers = 0;
{
alt_lookup_handler.get(torrent.getHash(), false, new DHTTrackerPluginAlt.LookupListener() {
@Override
public void foundPeer(InetSocketAddress address) {
peers++;
}
@Override
public boolean isComplete() {
return (false);
}
@Override
public void completed() {
status = TrackerPeerSource.ST_ONLINE;
}
});
}
@Override
public int getType() {
return (TrackerPeerSource.TP_DHT);
}
@Override
public String getName() {
return ("Mainline DHT");
}
@Override
public int getStatus() {
return (status);
}
@Override
public int getPeers() {
int result = peers;
if (result == 0 && status != TrackerPeerSource.ST_ONLINE) {
return (-1);
}
return (result);
}
@Override
public boolean isUpdating() {
return (status == TrackerPeerSource.ST_UPDATING);
}
};
return (new TrackerPeerSource[] { vuze_dht, alt_dht });
} else {
return (new TrackerPeerSource[] { vuze_dht });
}
}
use of com.biglybt.plugin.dht.DHTPluginContact in project BiglyBT by BiglySoftware.
the class DHTTrackerPlugin method trackerGet.
protected int trackerGet(final Download download, final RegistrationDetails details, final boolean derived_only) {
final long start = SystemTime.getCurrentTime();
final Torrent torrent = download.getTorrent();
final URL url_to_report = torrent.isDecentralised() ? torrent.getAnnounceURL() : DEFAULT_URL;
trackerTarget[] targets = details.getTargets(false);
final long[] max_retry = { 0 };
final boolean do_alt = alt_lookup_handler != null && (!(download.getFlag(Download.FLAG_LOW_NOISE) || download.getFlag(Download.FLAG_LIGHT_WEIGHT)));
int num_done = 0;
for (int i = 0; i < targets.length; i++) {
final trackerTarget target = targets[i];
int target_type = target.getType();
if (target_type == REG_TYPE_FULL && derived_only) {
continue;
} else if (target_type == REG_TYPE_DERIVED && dht.isSleeping()) {
continue;
}
increaseActive(download);
num_done++;
final boolean is_complete = isComplete(download);
dht.get(target.getHash(), "Tracker announce for '" + download.getName() + "'" + target.getDesc(), is_complete ? DHTPlugin.FLAG_SEEDING : DHTPlugin.FLAG_DOWNLOADING, NUM_WANT, target_type == REG_TYPE_FULL ? ANNOUNCE_TIMEOUT : ANNOUNCE_DERIVED_TIMEOUT, false, false, new DHTPluginOperationListener() {
List<String> addresses = new ArrayList<>();
List<Integer> ports = new ArrayList<>();
List<Integer> udp_ports = new ArrayList<>();
List<Boolean> is_seeds = new ArrayList<>();
List<String> flags = new ArrayList<>();
int seed_count;
int leecher_count;
int i2p_seed_count;
int i2p_leecher_count;
volatile boolean complete;
{
if (do_alt) {
alt_lookup_handler.get(target.getHash(), is_complete, new DHTTrackerPluginAlt.LookupListener() {
@Override
public void foundPeer(InetSocketAddress address) {
alternativePeerRead(address);
}
@Override
public boolean isComplete() {
return (complete && addresses.size() > 5);
}
@Override
public void completed() {
}
});
}
}
@Override
public boolean diversified() {
return (true);
}
@Override
public void starts(byte[] key) {
}
private void alternativePeerRead(InetSocketAddress peer) {
boolean try_injection = false;
synchronized (this) {
if (complete) {
try_injection = addresses.size() < 5;
} else {
try {
addresses.add(peer.getAddress().getHostAddress());
ports.add(peer.getPort());
udp_ports.add(0);
flags.add(null);
is_seeds.add(false);
leecher_count++;
} catch (Throwable e) {
}
}
}
if (try_injection) {
PeerManager pm = download.getPeerManager();
if (pm != null) {
pm.peerDiscovered(PEPeerSource.PS_DHT, peer.getAddress().getHostAddress(), peer.getPort(), 0, NetworkManager.getCryptoRequired(NetworkManager.CRYPTO_OVERRIDE_NONE));
}
}
}
@Override
public void valueRead(DHTPluginContact originator, DHTPluginValue value) {
synchronized (this) {
if (complete) {
return;
}
try {
String[] tokens = new String(value.getValue()).split(";");
String tcp_part = tokens[0].trim();
int sep = tcp_part.indexOf(':');
String ip_str = null;
String tcp_port_str;
if (sep == -1) {
tcp_port_str = tcp_part;
} else {
ip_str = tcp_part.substring(0, sep);
tcp_port_str = tcp_part.substring(sep + 1);
}
int tcp_port = Integer.parseInt(tcp_port_str);
if (tcp_port > 0 && tcp_port < 65536) {
String flag_str = null;
int udp_port = -1;
boolean has_i2p = false;
try {
for (int i = 1; i < tokens.length; i++) {
String token = tokens[i].trim();
if (token.length() > 0) {
if (Character.isDigit(token.charAt(0))) {
udp_port = Integer.parseInt(token);
if (udp_port <= 0 || udp_port >= 65536) {
udp_port = -1;
}
} else {
flag_str = token;
if (flag_str.contains("I")) {
has_i2p = true;
}
}
}
}
} catch (Throwable e) {
}
addresses.add(ip_str == null ? originator.getAddress().getAddress().getHostAddress() : ip_str);
ports.add(new Integer(tcp_port));
udp_ports.add(new Integer(udp_port == -1 ? originator.getAddress().getPort() : udp_port));
flags.add(flag_str);
if ((value.getFlags() & DHTPlugin.FLAG_DOWNLOADING) == 1) {
leecher_count++;
is_seeds.add(Boolean.FALSE);
if (has_i2p) {
i2p_leecher_count++;
}
} else {
is_seeds.add(Boolean.TRUE);
seed_count++;
if (has_i2p) {
i2p_seed_count++;
}
}
}
} catch (Throwable e) {
// in case we get crap back (someone spamming the DHT) just
// silently ignore
}
}
}
@Override
public void valueWritten(DHTPluginContact target, DHTPluginValue value) {
}
@Override
public void complete(byte[] key, boolean timeout_occurred) {
synchronized (this) {
if (complete) {
return;
}
complete = true;
}
if (target.getType() == REG_TYPE_FULL || (target.getType() == REG_TYPE_DERIVED && seed_count + leecher_count > 1)) {
log(download, "Get of '" + target.getDesc() + "' completed (elapsed=" + TimeFormatter.formatColonMillis(SystemTime.getCurrentTime() - start) + "), addresses=" + addresses.size() + ", seeds=" + seed_count + ", leechers=" + leecher_count);
}
decreaseActive(download);
int peers_found = addresses.size();
List<DownloadAnnounceResultPeer> peers_for_announce = new ArrayList<>();
// scale min and max based on number of active torrents
// we don't want more than a few announces a minute
int announce_per_min = 4;
int num_active = query_map.size();
int announce_min = Math.max(ANNOUNCE_MIN_DEFAULT, (num_active / announce_per_min) * 60 * 1000);
int announce_max = derived_only ? ANNOUNCE_MAX_DERIVED_ONLY : ANNOUNCE_MAX;
announce_min = Math.min(announce_min, announce_max);
current_announce_interval = announce_min;
final long retry = announce_min + peers_found * (long) (announce_max - announce_min) / NUM_WANT;
int download_state = download.getState();
boolean we_are_seeding = download_state == Download.ST_SEEDING;
try {
this_mon.enter();
int[] run_data = running_downloads.get(download);
if (run_data != null) {
boolean full = target.getType() == REG_TYPE_FULL;
int peer_count = we_are_seeding ? leecher_count : (seed_count + leecher_count);
run_data[1] = full ? seed_count : Math.max(run_data[1], seed_count);
run_data[2] = full ? leecher_count : Math.max(run_data[2], leecher_count);
run_data[3] = full ? peer_count : Math.max(run_data[3], peer_count);
run_data[4] = (int) (SystemTime.getCurrentTime() / 1000);
long absolute_retry = SystemTime.getCurrentTime() + retry;
if (absolute_retry > max_retry[0]) {
// only update next query time if none set yet
// or we appear to have set the existing one. If we
// don't do this then we'll overwrite any rescheduled
// announces
Long existing = (Long) query_map.get(download);
if (existing == null || existing.longValue() == max_retry[0]) {
max_retry[0] = absolute_retry;
query_map.put(download, new Long(absolute_retry));
}
}
}
} finally {
this_mon.exit();
}
putDetails put_details = details.getPutDetails();
String ext_address = put_details.getIPOverride();
if (ext_address == null) {
ext_address = dht.getLocalAddress().getAddress().getAddress().getHostAddress();
}
if (put_details.hasI2P()) {
if (we_are_seeding) {
if (i2p_seed_count > 0) {
i2p_seed_count--;
}
} else {
if (i2p_leecher_count > 0) {
i2p_leecher_count--;
}
}
}
if (i2p_seed_count + i2p_leecher_count > 0) {
download.setUserData(DOWNLOAD_USER_DATA_I2P_SCRAPE_KEY, new int[] { i2p_seed_count, i2p_leecher_count });
} else {
download.setUserData(DOWNLOAD_USER_DATA_I2P_SCRAPE_KEY, null);
}
for (int i = 0; i < addresses.size(); i++) {
if (we_are_seeding && ((Boolean) is_seeds.get(i)).booleanValue()) {
continue;
}
// remove ourselves
String ip = (String) addresses.get(i);
if (ip.equals(ext_address)) {
if (((Integer) ports.get(i)).intValue() == put_details.getTCPPort() && ((Integer) udp_ports.get(i)).intValue() == put_details.getUDPPort()) {
continue;
}
}
final int f_i = i;
peers_for_announce.add(new DownloadAnnounceResultPeer() {
@Override
public String getSource() {
return (PEPeerSource.PS_DHT);
}
@Override
public String getAddress() {
return ((String) addresses.get(f_i));
}
@Override
public int getPort() {
return (((Integer) ports.get(f_i)).intValue());
}
@Override
public int getUDPPort() {
return (((Integer) udp_ports.get(f_i)).intValue());
}
@Override
public byte[] getPeerID() {
return (null);
}
@Override
public short getProtocol() {
String flag = (String) flags.get(f_i);
short protocol = DownloadAnnounceResultPeer.PROTOCOL_NORMAL;
if (flag != null) {
if (flag.contains("C")) {
protocol = DownloadAnnounceResultPeer.PROTOCOL_CRYPT;
}
}
return (protocol);
}
});
}
if (target.getType() == REG_TYPE_DERIVED && peers_for_announce.size() > 0) {
PeerManager pm = download.getPeerManager();
if (pm != null) {
// try some limited direct injection
List<DownloadAnnounceResultPeer> temp = new ArrayList<>(peers_for_announce);
Random rand = new Random();
for (int i = 0; i < DIRECT_INJECT_PEER_MAX && temp.size() > 0; i++) {
DownloadAnnounceResultPeer peer = temp.remove(rand.nextInt(temp.size()));
log(download, "Injecting derived peer " + peer.getAddress() + " into " + download.getName());
Map<Object, Object> user_data = new HashMap<>();
user_data.put(Peer.PR_PRIORITY_CONNECTION, Boolean.TRUE);
pm.addPeer(peer.getAddress(), peer.getPort(), peer.getUDPPort(), peer.getProtocol() == DownloadAnnounceResultPeer.PROTOCOL_CRYPT, user_data);
}
}
}
if (download_state == Download.ST_DOWNLOADING || download_state == Download.ST_SEEDING) {
final DownloadAnnounceResultPeer[] peers = new DownloadAnnounceResultPeer[peers_for_announce.size()];
peers_for_announce.toArray(peers);
download.setAnnounceResult(new DownloadAnnounceResult() {
@Override
public Download getDownload() {
return (download);
}
@Override
public int getResponseType() {
return (DownloadAnnounceResult.RT_SUCCESS);
}
@Override
public int getReportedPeerCount() {
return (peers.length);
}
@Override
public int getSeedCount() {
return (seed_count);
}
@Override
public int getNonSeedCount() {
return (leecher_count);
}
@Override
public String getError() {
return (null);
}
@Override
public URL getURL() {
return (url_to_report);
}
@Override
public DownloadAnnounceResultPeer[] getPeers() {
return (peers);
}
@Override
public long getTimeToWait() {
return (retry / 1000);
}
@Override
public Map getExtensions() {
return (null);
}
});
}
// only inject the scrape result if the torrent is decentralised. If we do this for
// "normal" torrents then it can have unwanted side-effects, such as stopping the torrent
// due to ignore rules if there are no downloaders in the DHT - bthub backup, for example,
// isn't scrapable...
// hmm, ok, try being a bit more relaxed about this, inject the scrape if
// we have any peers.
boolean inject_scrape = leecher_count > 0;
DownloadScrapeResult result = download.getLastScrapeResult();
if (result == null || result.getResponseType() == DownloadScrapeResult.RT_ERROR) {
} else {
synchronized (scrape_injection_map) {
int[] prev = (int[]) scrape_injection_map.get(download);
if (prev != null && prev[0] == result.getSeedCount() && prev[1] == result.getNonSeedCount()) {
inject_scrape = true;
}
}
}
if (torrent.isDecentralised() || inject_scrape) {
// make sure that the injected scrape values are consistent
// with our currently connected peers
PeerManager pm = download.getPeerManager();
int local_seeds = 0;
int local_leechers = 0;
if (pm != null) {
Peer[] dl_peers = pm.getPeers();
for (int i = 0; i < dl_peers.length; i++) {
Peer dl_peer = dl_peers[i];
if (dl_peer.getPercentDoneInThousandNotation() == 1000) {
local_seeds++;
} else {
local_leechers++;
}
}
}
final int f_adj_seeds = Math.max(seed_count, local_seeds);
final int f_adj_leechers = Math.max(leecher_count, local_leechers);
synchronized (scrape_injection_map) {
scrape_injection_map.put(download, new int[] { f_adj_seeds, f_adj_leechers });
}
try {
this_mon.enter();
int[] run_data = running_downloads.get(download);
if (run_data == null) {
run_data = run_data_cache.get(download);
}
if (run_data != null) {
run_data[1] = f_adj_seeds;
run_data[2] = f_adj_leechers;
run_data[4] = (int) (SystemTime.getCurrentTime() / 1000);
}
} finally {
this_mon.exit();
}
download.setScrapeResult(new DownloadScrapeResult() {
@Override
public Download getDownload() {
return (download);
}
@Override
public int getResponseType() {
return (DownloadScrapeResult.RT_SUCCESS);
}
@Override
public int getSeedCount() {
return (f_adj_seeds);
}
@Override
public int getNonSeedCount() {
return (f_adj_leechers);
}
@Override
public long getScrapeStartTime() {
return (start);
}
@Override
public void setNextScrapeStartTime(long nextScrapeStartTime) {
}
@Override
public long getNextScrapeStartTime() {
return (SystemTime.getCurrentTime() + retry);
}
@Override
public String getStatus() {
return ("OK");
}
@Override
public URL getURL() {
return (url_to_report);
}
});
}
}
});
}
return (num_done);
}
Aggregations