/*
* Copyright (C) 2012-2015 DataStax 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.datastax.driver.core;
import com.datastax.driver.core.policies.ConstantReconnectionPolicy;
import com.google.common.util.concurrent.Uninterruptibles;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.net.InetSocketAddress;
import static com.datastax.driver.core.Assertions.assertThat;
import static com.datastax.driver.core.HostDistance.LOCAL;
import static com.datastax.driver.core.TestUtils.nonDebouncingQueryOptions;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.scassandra.http.client.ClosedConnectionReport.CloseType.CLOSE;
public class HostConnectionPoolMultiTest {
private ScassandraCluster scassandra;
private Cluster cluster;
@BeforeMethod(groups = {"short", "long"})
private void setUp() {
scassandra = ScassandraCluster.builder().withNodes(2).build();
scassandra.init();
}
@AfterMethod(groups = {"short", "long"}, alwaysRun = true)
private void tearDown() {
if (cluster != null) {
cluster.close();
}
scassandra.stop();
}
private void createCluster(int core, int max) {
PoolingOptions poolingOptions = new PoolingOptions().setConnectionsPerHost(LOCAL, core, max);
SocketOptions socketOptions = new SocketOptions().setReadTimeoutMillis(1000);
cluster = Cluster.builder()
.addContactPoints(scassandra.address(1).getAddress())
.withPort(scassandra.getBinaryPort())
.withQueryOptions(nonDebouncingQueryOptions())
.withPoolingOptions(poolingOptions)
.withSocketOptions(socketOptions)
.withReconnectionPolicy(new ConstantReconnectionPolicy(1000))
.build();
cluster.connect();
}
/**
* Ensures that if all connections fail to a host on pool init that the host is marked down.
*
* @jira_ticket JAVA-544
* @test_category connection:connection_pool
* @since 2.0.11
*/
@Test(groups = "short")
public void should_mark_host_down_if_all_connections_fail_on_init() {
// Prevent any connections on node 2.
scassandra.node(2).currentClient().disableListener();
createCluster(8, 8);
// Node 2 should be in a down state while node 1 stays up.
assertThat(cluster).host(2).goesDownWithin(10, SECONDS);
assertThat(cluster).host(1).isUp();
// Node 2 should come up as soon as it is able to reconnect.
scassandra.node(2).currentClient().enableListener();
assertThat(cluster).host(2).comesUpWithin(2, SECONDS);
}
/**
* Ensures that if the control connection goes down, but the Host bound the control connection
* still has an up pool, the Host should remain up and the Control Connection should be replaced.
*
* @jira_ticket JAVA-544
* @test_category connection:connection_pool
* @since 2.0.11
*/
@Test(groups = "short")
public void should_replace_control_connection_if_it_goes_down_but_host_remains_up() {
createCluster(1, 2);
// Ensure control connection is on node 1.
assertThat(cluster).usesControlHost(1);
// Identify the socket associated with the control connection.
Connection controlConnection = cluster.manager.controlConnection.connectionRef.get();
InetSocketAddress controlSocket = (InetSocketAddress) controlConnection.channel.localAddress();
// Close the control connection.
scassandra.node(1).currentClient()
.closeConnection(CLOSE, controlSocket);
// Sleep reconnect interval * 2 to allow time to reconnect.
Uninterruptibles.sleepUninterruptibly(2, SECONDS);
// Ensure the control connection was replaced and host 1 remains up.
assertThat(cluster).hasOpenControlConnection()
.host(1).isUp();
assertThat(cluster.manager.controlConnection.connectionRef.get()).isNotEqualTo(controlConnection);
}
}