dev@grizzly.java.net

Re: About SSLConnectionTest's failure and PipelineThreadPool issue

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Tue, 19 May 2009 11:29:32 -0400

Salut,

Bongjae Chang wrote:
> Hi,
>
> I received the following error when I ran SSLConnectionTest on 4 CPUs
>
> -------------------------------------------------------------------------------
> Test set: com.sun.grizzly.SSLConnectionTest
> -------------------------------------------------------------------------------
> Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 53.219
> sec <<< FAILURE!
> testSeveralPackets(com.sun.grizzly.SSLConnectionTest) Time elapsed: 41
> sec <<< FAILURE!
> junit.framework.AssertionFailedError: Handshake is not completed!
> testString: Hello. Client#0 Packet#000 latchCounter: 1 isConnected: false
> at junit.framework.Assert.fail(Assert.java:47)
> at junit.framework.Assert.assertTrue(Assert.java:20)
> at
> com.sun.grizzly.SSLConnectionTest.testSeveralPackets(SSLConnectionTest.java:187)
>
> When I debugged, I could find that this case was also failed for lack of
> thread pool's capacity. :-(
>
> See the following code:
>
> In SSLConnectionTest.java
> ---
> ...
> public static final int CLIENTS_COUNT = 10;
> ...
> public void testSeveralPackets() throws IOException {
> ...
> controller.setThreadPool(*new PipelineThreadPool("", 5,
> CLIENTS_COUNT * 2, Integer.MAX_VALUE, TimeUnit.MILLISECONDS)*);
> }
> ---
>
> It means that min is 5 and max is 20.
>
> At first, I thought that the max which had 20 was perhaps enough for
> testing this case, but this case was failed.
>
> So, I reviewed PipelineThreadPool in order to confirm whether it
> increased threads until max size or not.
>
> See the following code:
>
> In PipelineThreadPool.java
> ---
> public void execute(Runnable task) {
> if (task == null){
> throw new IllegalArgumentException("Runnable task is null");
> }
>
> int ac;
> while((ac=aliveworkerCount.get())<maxPoolSize &&
> *queueSize.get()>0* && running){
> if (aliveworkerCount.compareAndSet(ac, ac+1)){
> startWorker(new Worker(task, false));
> return;
> }
> }
> if (running){
> workQueue.offer(task);
> queueSize.incrementAndGet();
> }
> }
> ---
>
> Unfortunately, PipelineThreadPool allows a thread to be increased when
> queue size is only above 0.
>
> Then the sixth task will be queued without thread's increment if five
> former tasks are still running, and it will not be executed until the
> seventh task will come.
>
> Of course, I think that PipelineThreadPool is better than JDK's
> ThreadPoolExecutor in point of thread-increment-policy, but it should
> also be improved at this point.

Agree. The Grizzly 1.0 logic was:

>
> // Create worker threads if we know we will run out of them
> if (threadCount < maxThreads && waitingThreads < (queueSize + 1)){
> int left = maxThreads - threadCount;
> if (threadsIncrement > left){
> threadsIncrement = left;
> }
> increaseWorkerThread(threadsIncrement,true);
> }

This proved to quite effective.


>
>
>
> Anyway... I proposed the following patch.
>
> In SSLConnectionTest.java
> ---
> ...
> public static final int CLIENTS_COUNT = 10;
> ...
> public void testSeveralPackets() throws IOException {
> ...
> // Use the default thread pool which is configued automatically
> //controller.setThreadPool(*new PipelineThreadPool("", 5,
> CLIENTS_COUNT * 2, Integer.MAX_VALUE, TimeUnit.MILLISECONDS)*);
> }
> ---
>
> Thanks.
>
> PS) I tested this case with my proposed thread
> pool(https://grizzly.dev.java.net/issues/show_bug.cgi?id=587)
> experimentally, it works well. :-)

OK now that you have commiter right, go ahead and commit :-)

Thanks!

-- Jeanfrancois


>
> --
> Bongjae Chang