Fix a bug in QosFilter (#14859)

QoSFilter class is trying to parse the timeout as an integer. We need to round a value of query timeout that is higher than INT.MAX to INT.MAX.
This commit is contained in:
Abhishek Agarwal 2023-08-21 13:00:41 +05:30 committed by GitHub
parent 263ac36e8d
commit 9065ef1aff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 5 deletions

View File

@ -76,7 +76,7 @@ public class DeterminePartitionsJobSamplerTest
}
double expect = total * 1.0 / samplingFactor;
double error = Math.abs(hit - expect) / expect;
Assert.assertTrue(error < 0.01);
Assert.assertTrue(String.valueOf(error), error < 0.02);
}
@Test
@ -97,6 +97,6 @@ public class DeterminePartitionsJobSamplerTest
}
double expect = total * 1.0 / samplingFactor;
double error = Math.abs(hit - expect) / expect;
Assert.assertTrue(error < 0.01);
Assert.assertTrue(String.valueOf(error), error < 0.02);
}
}

View File

@ -94,10 +94,15 @@ public class JettyBindings
@Override
public Map<String, String> getInitParameters()
{
if (timeoutMs >= 0) {
return ImmutableMap.of("maxRequests", String.valueOf(maxRequests), "suspendMs", String.valueOf(timeoutMs));
if (timeoutMs < 0) {
return ImmutableMap.of("maxRequests", String.valueOf(maxRequests));
}
return ImmutableMap.of("maxRequests", String.valueOf(maxRequests));
if (timeoutMs > Integer.MAX_VALUE) {
// QoSFilter tries to parse the suspendMs parameter as an int, so we can't set it to more than Integer
// .MAX_VALUE.
return ImmutableMap.of("maxRequests", String.valueOf(maxRequests), "suspendMs", String.valueOf(Integer.MAX_VALUE));
}
return ImmutableMap.of("maxRequests", String.valueOf(maxRequests), "suspendMs", String.valueOf(timeoutMs));
}
@Override

View File

@ -22,6 +22,7 @@ package org.apache.druid.server.initialization;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Binder;
import com.google.inject.Injector;
@ -45,12 +46,16 @@ import org.apache.druid.server.initialization.jetty.JettyServerInitializer;
import org.apache.druid.server.security.AuthTestUtils;
import org.apache.druid.server.security.AuthorizerMapper;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlets.QoSFilter;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.junit.Assert;
import org.junit.Test;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import java.net.URL;
import java.util.Enumeration;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicLong;
@ -193,4 +198,58 @@ public class JettyQosTest extends BaseJettyTest
// check that fast requests finished quickly
Assert.assertTrue(fastElapsed.get() / fastCount.get() < 500);
}
@Test
public void testQoSFilterMaxTimeout()
{
QoSFilter filter = new QoSFilter();
JettyBindings.QosFilterHolder qosFilterHolder = new JettyBindings.QosFilterHolder(new String[]{"/slow/*"}, 1,
Long.MAX_VALUE
);
filter.init(new QoSFilterConfig(qosFilterHolder));
Assert.assertEquals(Integer.MAX_VALUE, filter.getSuspendMs());
}
@Test
public void testQoSFilterNoTimeout()
{
QoSFilter filter = new QoSFilter();
JettyBindings.QosFilterHolder qosFilterHolder = new JettyBindings.QosFilterHolder(new String[]{"/slow/*"}, 1);
filter.init(new QoSFilterConfig(qosFilterHolder));
Assert.assertEquals(-1, filter.getSuspendMs());
}
private static class QoSFilterConfig implements FilterConfig
{
private JettyBindings.QosFilterHolder qosFilterHolder;
public QoSFilterConfig(JettyBindings.QosFilterHolder qosFilterHolder)
{
this.qosFilterHolder = qosFilterHolder;
}
@Override
public String getFilterName()
{
return "dummy";
}
@Override
public ServletContext getServletContext()
{
return null;
}
@Override
public String getInitParameter(String name)
{
return qosFilterHolder.getInitParameters().get(name);
}
@Override
public Enumeration<String> getInitParameterNames()
{
return Iterators.asEnumeration(qosFilterHolder.getInitParameters().keySet().iterator());
}
}
}