final DistributedDatabase db = plugin_interface.getDistributedDatabase();
final List potential_contacts = new ArrayList();
final AESemaphore potential_contacts_sem = new AESemaphore( "MagnetPlugin:liveones" );
final AEMonitor potential_contacts_mon = new AEMonitor( "MagnetPlugin:liveones" );
final int[] outstanding = {0};
final boolean[] lookup_complete = {false};
listener.reportActivity( getMessageText( "report.searching" ));
DistributedDatabaseListener ddb_listener =
new DistributedDatabaseListener()
{
private Set found_set = new HashSet();
public void
event(
DistributedDatabaseEvent event )
{
int type = event.getType();
if ( type == DistributedDatabaseEvent.ET_OPERATION_STARTS ){
// give live results a chance before kicking in explicit ones
if ( sources.length > 0 ){
new DelayedEvent(
"MP:sourceAdd",
10*1000,
new AERunnable()
{
public void
runSupport()
{
addExplicitSources();
}
});
}
}else if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
contactFound( event.getValue().getContact());
}else if ( type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ||
type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ){
listener.reportActivity( getMessageText( "report.found", String.valueOf( found_set.size())));
// now inject any explicit sources
addExplicitSources();
try{
potential_contacts_mon.enter();
lookup_complete[0] = true;
}finally{
potential_contacts_mon.exit();
}
potential_contacts_sem.release();
}
}
protected void
addExplicitSources()
{
for (int i=0;i<sources.length;i++){
try{
contactFound( db.importContact(sources[i]));
}catch( Throwable e ){
Debug.printStackTrace(e);
}
}
}
public void
contactFound(
final DistributedDatabaseContact contact )
{
String key = contact.getAddress().toString();
synchronized( found_set ){
if ( found_set.contains( key )){
return;
}
found_set.add( key );
}
if ( listener.verbose()){
listener.reportActivity( getMessageText( "report.found", contact.getName()));
}
try{
potential_contacts_mon.enter();
outstanding[0]++;
}finally{
potential_contacts_mon.exit();
}
contact.isAlive(
20*1000,
new DistributedDatabaseListener()
{
public void
event(
DistributedDatabaseEvent event)
{
try{
boolean alive = event.getType() == DistributedDatabaseEvent.ET_OPERATION_COMPLETE;
if ( listener.verbose()){
listener.reportActivity(
getMessageText( alive?"report.alive":"report.dead", contact.getName()));
}
try{
potential_contacts_mon.enter();
Object[] entry = new Object[]{ new Boolean( alive ), contact};
boolean added = false;
if ( alive ){
// try and place before first dead entry
for (int i=0;i<potential_contacts.size();i++){
if (!((Boolean)((Object[])potential_contacts.get(i))[0]).booleanValue()){
potential_contacts.add(i, entry );
added = true;
break;
}
}
}
if ( !added ){
potential_contacts.add( entry ); // dead at end
}
}finally{
potential_contacts_mon.exit();
}
}finally{
try{
potential_contacts_mon.enter();
outstanding[0]--;
}finally{
potential_contacts_mon.exit();
}
potential_contacts_sem.release();
}
}
});
}
};
db.read(
ddb_listener,
db.createKey( hash, "Torrent download lookup for '" + ByteFormatter.encodeString( hash ) + "'" ),
timeout,
DistributedDatabase.OP_EXHAUSTIVE_READ | DistributedDatabase.OP_PRIORITY_HIGH );
long remaining = timeout;
long overall_start = SystemTime.getMonotonousTime();
boolean sl_enabled = secondary_lookup.getValue() && FeatureAvailability.isMagnetSLEnabled();
long secondary_lookup_time = -1;
long last_found = -1;
final Object[] secondary_result = { null };
while( remaining > 0 ){
try{
potential_contacts_mon.enter();
if ( lookup_complete[0] &&
potential_contacts.size() == 0 &&
outstanding[0] == 0 ){
break;
}
}finally{
potential_contacts_mon.exit();
}
while( remaining > 0 ){
long wait_start = SystemTime.getMonotonousTime();
boolean got_sem = potential_contacts_sem.reserve( 1000 );
long now = SystemTime.getMonotonousTime();
remaining -= ( now - wait_start );
if ( got_sem ){
last_found = now;
break;
}else{
if ( sl_enabled ){
if ( secondary_lookup_time == -1 ){
long base_time;
if ( last_found == -1 || now - overall_start > 60*1000 ){
base_time = overall_start;
}else{
base_time = last_found;
}
long time_so_far = now - base_time;
if ( time_so_far > SECONDARY_LOOKUP_DELAY ){
secondary_lookup_time = SystemTime.getMonotonousTime();
doSecondaryLookup( listener, secondary_result, hash, args );
}
}else{
try{
byte[] torrent = getSecondaryLookupResult( secondary_result );
if ( torrent != null ){
return( torrent );
}
}catch( ResourceDownloaderException e ){
// ignore, we just continue processing
}
}
}
continue;
}
}
DistributedDatabaseContact contact;
boolean live_contact;
try{
potential_contacts_mon.enter();
// System.out.println( "rem=" + remaining + ",pot=" + potential_contacts.size() + ",out=" + outstanding[0] );
if ( potential_contacts.size() == 0 ){
if ( outstanding[0] == 0 ){
break;
}else{
continue;
}
}else{
Object[] entry = (Object[])potential_contacts.remove(0);
live_contact = ((Boolean)entry[0]).booleanValue();
contact = (DistributedDatabaseContact)entry[1];
}
}finally{
potential_contacts_mon.exit();
}
// System.out.println( "magnetDownload: " + contact.getName() + ", live = " + live_contact );
if ( !live_contact ){