Improve logging, correctly handle redemption, use a thread-pool

cusax-fix
Ingo Bauersachs 13 years ago
parent ca2b2738e3
commit 9426348317

@ -10,6 +10,7 @@
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import net.java.sip.communicator.service.dns.*;
import net.java.sip.communicator.util.*;
@ -43,13 +44,13 @@ public class ParallelResolverImpl
* class and its instances for logging output.
*/
private static final Logger logger = Logger
.getLogger(ParallelResolverImpl.class.getName());
.getLogger(ParallelResolverImpl.class);
/**
* Indicates whether we are currently in a mode where all DNS queries are
* sent to both the primary and the backup DNS servers.
*/
private static boolean redundantMode = false;
private volatile static boolean redundantMode = false;
/**
* The currently configured number of milliseconds that we need to wait
@ -87,11 +88,15 @@ public class ParallelResolverImpl
*/
private ExtendedResolver backupResolver;
/** Thread pool that processes the backup queries. */
private ExecutorService backupQueriesPool;
/**
* Creates a new instance of this class.
*/
ParallelResolverImpl()
{
backupQueriesPool = Executors.newCachedThreadPool();
DnsUtilActivator.getConfigurationService()
.addPropertyChangeListener(this);
initProperties();
@ -117,8 +122,8 @@ private void initProperties()
}
catch(UnknownHostException exc)
{
logger.warn("Oh! Seems like our primary DNS is down!"
+ "Don't panic! We'll try to fall back to "
logger
.warn("Seems like the primary DNS is down, trying fallback to "
+ customResolverIP);
}
@ -178,7 +183,7 @@ private void setBackupServers(InetSocketAddress[] backupServers)
//this shouldn't be thrown since we don't do any DNS querying
//in here. this is why we take an InetSocketAddress as a param.
throw new IllegalStateException("The impossible just happened: "
+"we could not initialize our backup DNS resolver");
+ "we could not initialize our backup DNS resolver");
}
}
@ -193,23 +198,12 @@ private void setBackupServers(InetSocketAddress[] backupServers)
public Message send(Message query)
throws IOException
{
ParallelResolution resolution = new ParallelResolution(query);
resolution.sendFirstQuery();
//make a copy of the redundant mode variable in case we are currently
//completed a redemption that started earlier.
boolean redundantModeCopy;
synchronized(redemptionLock)
{
redundantModeCopy = redundantMode;
}
//if we are not in redundant mode we should wait a bit and see how this
//goes. if we get a reply we could return bravely.
if(!redundantModeCopy)
if(!redundantMode)
{
if(resolution.waitForResponse(currentDnsPatience))
{
@ -222,8 +216,10 @@ public Message send(Message query)
{
redundantMode = true;
redemptionStatus = currentDnsRedemption;
logger.info("Primary DNS seems laggy as we got no "
+"response for " + currentDnsPatience + "ms. "
logger.info("Primary DNS seems laggy: "
+ "no response for " + query.getQuestion().getName()
+ "/" + Type.string(query.getQuestion().getType())
+ " after " + currentDnsPatience + "ms. "
+ "Enabling redundant mode.");
}
}
@ -231,7 +227,6 @@ public Message send(Message query)
//we are definitely in redundant mode now
resolution.sendBackupQueries();
resolution.waitForResponse(0);
//check if it is time to end redundant mode.
@ -270,7 +265,7 @@ public Message send(Message query)
*/
public Object sendAsync(final Message query, final ResolverListener listener)
{
return null;
throw new UnsupportedOperationException("Not implemented");
}
/**
@ -448,7 +443,7 @@ private boolean isResponseSatisfactory(Message response)
* our default and backup servers and returns as soon as we get one or until
* our default resolver fails.
*/
private class ParallelResolution extends Thread
private class ParallelResolution implements Runnable
{
/**
* The query that we have sent to the default and backup DNS servers.
@ -459,7 +454,7 @@ private class ParallelResolution extends Thread
* The field where we would store the first incoming response to our
* query.
*/
public Message response;
private volatile Message response;
/**
* The field where we would store the first error we receive from a DNS
@ -470,12 +465,12 @@ private class ParallelResolution extends Thread
/**
* Indicates whether we are still waiting for an answer from someone
*/
private boolean done = false;
private volatile boolean done = false;
/**
* Indicates that a response was received from the primary resolver.
*/
private boolean primaryResolverRespondedFirst = true;
private volatile boolean primaryResolverRespondedFirst = true;
/**
* Creates a {@link ParallelResolution} for the specified <tt>query</tt>
@ -485,7 +480,6 @@ private class ParallelResolution extends Thread
*/
public ParallelResolution(final Message query)
{
super("ParallelResolutionThread");
this.query = query;
}
@ -495,7 +489,7 @@ public ParallelResolution(final Message query)
*/
public void sendFirstQuery()
{
start();
ParallelResolverImpl.this.backupQueriesPool.execute(this);
}
/**
@ -509,19 +503,24 @@ public void run()
{
localResponse = defaultResolver.send(query);
}
catch (Throwable exc)
catch (SocketTimeoutException exc)
{
logger.info("Exception occurred during parallel DNS resolving" +
exc, exc);
logger.info("Default DNS resolver timed out.");
this.exception = exc;
}
synchronized(this)
catch (Throwable exc)
{
logger.info("Default DNS resolver failed", exc);
this.exception = exc;
}
//if the backup resolvers had already replied we ignore the
//reply of the primary one whatever it was.
if(done)
return;
synchronized(this)
{
//if there was a response we're only done if it is satisfactory
if( localResponse != null
&& isResponseSatisfactory(localResponse))
@ -529,6 +528,7 @@ && isResponseSatisfactory(localResponse))
response = localResponse;
done = true;
}
notify();
}
}
@ -538,22 +538,25 @@ && isResponseSatisfactory(localResponse))
*/
public void sendBackupQueries()
{
logger.info("Send DNS queries to backup resolvers");
//yes. a second thread in the thread ... it's ugly but it works
//and i do want to keep code simple to read ... this whole parallel
//resolving is complicated enough as it is.
new Thread(){
backupQueriesPool.execute(new Runnable(){
@Override
public void run()
{
synchronized(ParallelResolution.this)
{
if (done)
{
return;
}
Message localResponse = null;
try
{
logger.info("Sending query for "
+ query.getQuestion().getName() + "/"
+ Type.string(query.getQuestion().getType())
+ " to backup resolvers");
localResponse = backupResolver.send(query);
}
catch (Throwable exc)
@ -567,18 +570,26 @@ public void run()
//if the default resolver has already replied we
//ignore the reply of the backup ones.
if(done)
{
return;
}
synchronized(ParallelResolution.this)
{
//contrary to responses from the primary resolver,
//in this case we don't care whether the response is
//satisfying: if it isn't, there's nothing we can do
if (response == null)
{
response = localResponse;
done = true;
primaryResolverRespondedFirst = false;
}
done = true;
ParallelResolution.this.notify();
}
}
}.start();
});
}
/**
@ -636,6 +647,11 @@ public Message returnResponseOrThrowUp()
{
return response;
}
else if (exception instanceof SocketTimeoutException)
{
logger.warn("DNS resolver timed out");
throw (IOException) exception;
}
else if (exception instanceof IOException)
{
logger.warn("IO exception while using DNS resolver", exception);
@ -664,6 +680,7 @@ else if (exception instanceof Error)
@SuppressWarnings("serial")
private final Set<String> configNames = new HashSet<String>(5)
{{
add(DnsUtilActivator.PNAME_BACKUP_RESOLVER_ENABLED);
add(DnsUtilActivator.PNAME_BACKUP_RESOLVER);
add(DnsUtilActivator.PNAME_BACKUP_RESOLVER_FALLBACK_IP);
add(DnsUtilActivator.PNAME_BACKUP_RESOLVER_PORT);

Loading…
Cancel
Save