/* * Copyright 2013 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.netflix.suro.connection; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.netflix.governator.configuration.PropertiesConfigurationProvider; import com.netflix.governator.guice.BootstrapBinder; import com.netflix.governator.guice.BootstrapModule; import com.netflix.governator.guice.LifecycleInjector; import com.netflix.governator.lifecycle.LifecycleManager; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.suro.ClientConfig; import com.netflix.suro.SuroServer4Test; import com.netflix.suro.thrift.ResultCode; import com.netflix.suro.thrift.TMessageSet; import org.apache.thrift.TException; import org.junit.After; import org.junit.Test; import java.util.List; import java.util.Properties; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; public class TestConnectionOutPool { private Injector injector; private List<SuroServer4Test> servers; private Properties props = new Properties(); private ConnectionPool pool; @Test public void testOutPool() throws Exception { props.put(ClientConfig.ENABLE_OUTPOOL, "true"); setup(); ExecutorService executors = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; ++i) { executors.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 5; ++i) { try { ConnectionPool.SuroConnection client = pool.chooseConnection(); assertEquals(client.send(TestConnectionPool.createMessageSet(100)).getResultCode(), ResultCode.OK); pool.endConnection(client); } catch (TException e) { fail(e.getMessage()); } } } }); } executors.shutdown(); executors.awaitTermination(10, TimeUnit.SECONDS); assertTrue(pool.getOutPoolSize() > 0); try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } TestConnectionPool.checkMessageSetCount(servers, 50, false); } public void setup() throws Exception { servers = TestConnectionPool.startServers(1); props.put(ClientConfig.LB_SERVER, TestConnectionPool.createConnectionString(servers)); props.put(ClientConfig.CONNECTION_TIMEOUT, Integer.toString(Integer.MAX_VALUE)); injector = LifecycleInjector.builder() .withBootstrapModule(new BootstrapModule() { @Override public void configure(BootstrapBinder binder) { binder.bindConfigurationProvider().toInstance(new PropertiesConfigurationProvider(props)); } }) .withAdditionalModules(new AbstractModule() { @Override protected void configure() { bind(ILoadBalancer.class).to(StaticLoadBalancer.class); } }) .build().createInjector(); injector.getInstance(LifecycleManager.class).start(); pool = injector.getInstance(ConnectionPool.class); assertEquals(pool.getPoolSize(), 1); } @After public void after() { TestConnectionPool.shutdownServers(servers); } @Test public void shouldConnectionOutPoolStopGrowing() throws Exception { setup(); for (SuroServer4Test server : servers) { server.setHoldConnection(); } int numThreads = 10; final CountDownLatch latch = new CountDownLatch(numThreads); ExecutorService executors = Executors.newFixedThreadPool(numThreads); for (int i = 0; i < numThreads; ++i) { executors.execute(new Runnable() { @Override public void run() { TMessageSet messageSet = TestConnectionPool.createMessageSet(100); boolean set = true; while (true) { ConnectionPool.SuroConnection connection = pool.chooseConnection(); if (set) { latch.countDown(); set = false; } if (connection == null) { continue; } try { ResultCode result = connection.send(messageSet).getResultCode(); System.out.println("result code: " + result); if (result == ResultCode.OK) { break; } } catch (Exception e) { } finally { pool.endConnection(connection); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("finished"); } }); } latch.await(); assertEquals(pool.getOutPoolSize(), 0); for (SuroServer4Test server : servers) { server.cancelHoldConnection(); } executors.shutdown(); executors.awaitTermination(60, TimeUnit.SECONDS); try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } TestConnectionPool.checkMessageSetCount(servers, numThreads, false); } }