package com.netflix.astyanax.connectionpool.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.math.BigInteger;
import java.util.List;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.astyanax.connectionpool.ConnectionPool;
import com.netflix.astyanax.connectionpool.ConnectionPoolConfiguration;
import com.netflix.astyanax.connectionpool.Host;
import com.netflix.astyanax.connectionpool.HostConnectionPool;
import com.netflix.astyanax.connectionpool.Operation;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.partitioner.OrderedBigIntegerPartitioner;
import com.netflix.astyanax.retry.RetryPolicy;
import com.netflix.astyanax.retry.RunOnce;
import com.netflix.astyanax.serializers.BigIntegerSerializer;
import com.netflix.astyanax.test.TestClient;
import com.netflix.astyanax.test.TestConnectionFactory;
import com.netflix.astyanax.test.TestConstants;
import com.netflix.astyanax.test.TestOperation;
import com.netflix.astyanax.test.TestTokenRange;
import com.netflix.astyanax.test.TokenTestOperation;
import com.netflix.astyanax.util.TokenGenerator;
public class TokenAwareConnectionPoolTest extends BaseConnectionPoolTest {
private static Logger LOG = LoggerFactory.getLogger(TokenAwareConnectionPoolTest.class);
private static Operation<TestClient, String> dummyOperation = new TestOperation();
protected ConnectionPool<TestClient> createPool() {
ConnectionPoolConfiguration config = new ConnectionPoolConfigurationImpl(
TestConstants.CLUSTER_NAME + "_" + TestConstants.KEYSPACE_NAME)
.setPartitioner(OrderedBigIntegerPartitioner.get());
config.initialize();
CountingConnectionPoolMonitor monitor = new CountingConnectionPoolMonitor();
return new TokenAwareConnectionPoolImpl<TestClient>(
config, new TestConnectionFactory(config, monitor), monitor);
}
@Test
public void testTokenMappingForMidRangeTokens() throws ConnectionException {
ConnectionPool<TestClient> cp = createPool();
List<Host> ring1 = makeRing(3, 1, 1);
LOG.info("testTokenMappingForMidRangeTokens\n" + TestTokenRange.getRingDetails(ring1));
cp.setHosts(ring1);
BigInteger threeNodeRingIncrement = TokenGenerator.MAXIMUM.divide(new BigInteger("3"));
RetryPolicy retryPolicy = new RunOnce();
BigInteger key = BigInteger.ZERO;
LOG.info(key.toString() + " 127.0.1.2");
OperationResult<String> result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.2",result.getHost().getIpAddress());
key = BigInteger.ONE;
LOG.info(key.toString() + " 127.0.1.0");
result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.0",result.getHost().getIpAddress());
key = threeNodeRingIncrement.subtract(BigInteger.ONE);
LOG.info(key.toString() + " 127.0.1.0");
result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.0",result.getHost().getIpAddress());
key = threeNodeRingIncrement;
LOG.info(key.toString() + " 127.0.1.0");
result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.0",result.getHost().getIpAddress());
key = threeNodeRingIncrement.add(BigInteger.ONE);
LOG.info(key.toString() + " 127.0.1.1");
result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.1",result.getHost().getIpAddress());
key = threeNodeRingIncrement.add(threeNodeRingIncrement).add(BigInteger.ONE);
LOG.info(key.toString() + " 127.0.1.1");
result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.1",result.getHost().getIpAddress());
key = threeNodeRingIncrement.add(threeNodeRingIncrement).add(BigInteger.ONE).add(BigInteger.ONE);
LOG.info(key.toString() + " 127.0.1.2");
result = cp.executeWithFailover(new TokenTestOperation(key), retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.2",result.getHost().getIpAddress());
}
@Test
public void testTokenMappingForOrdinalTokens() throws ConnectionException {
ConnectionPool<TestClient> cp = createPool();
// the following will generate a ring of two nodes with the following characteristics;
// node1 - ip = 127.0.1.0, token ownership range = (1200 , 0]
// node1 - ip = 127.0.1.1, token ownership range = (0 , 600]
// node1 - ip = 127.0.1.1, token ownership range = (600 , 1200]
List<Host> ring1 = TestTokenRange.makeRing(3, 1, 1, BigInteger.ZERO, new BigInteger("1800"));
LOG.info("testTokenMappingForOrdinalTokens\n" + TestTokenRange.getRingDetails(ring1));
cp.setHosts(ring1);
BigInteger threeNodeRingIncrement = new BigInteger("600");
Operation<TestClient, String> firstHostOp = new TokenTestOperation(BigInteger.ZERO);
Operation<TestClient, String> secondHostOp = new TokenTestOperation(threeNodeRingIncrement);
Operation<TestClient, String> thirdHostOp = new TokenTestOperation(threeNodeRingIncrement.multiply(new BigInteger("2")));
Operation<TestClient, String> maxTokenHostOp = new TokenTestOperation(threeNodeRingIncrement.multiply(new BigInteger("3")));
LOG.info(BigIntegerSerializer.get().fromByteBuffer(firstHostOp.getRowKey()).toString());
LOG.info(BigIntegerSerializer.get().fromByteBuffer(secondHostOp.getRowKey()).toString());
LOG.info(BigIntegerSerializer.get().fromByteBuffer(thirdHostOp.getRowKey()).toString());
LOG.info(BigIntegerSerializer.get().fromByteBuffer(maxTokenHostOp.getRowKey()).toString());
RetryPolicy retryPolicy = new RunOnce();
OperationResult<String> result = cp.executeWithFailover(firstHostOp, retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.2",result.getHost().getIpAddress());
result = cp.executeWithFailover(secondHostOp, retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.0",result.getHost().getIpAddress());
result = cp.executeWithFailover(thirdHostOp, retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.1",result.getHost().getIpAddress());
result = cp.executeWithFailover(maxTokenHostOp, retryPolicy);
assertNotNull(result);
assertEquals("127.0.1.2",result.getHost().getIpAddress());
}
@Test
public void testTokenToHostMappingInWrappedRange() throws ConnectionException {
ConnectionPool<TestClient> cp = createPool();
// the following will generate a ring of two nodes with the following characteristics;
// node1 - ip = 127.0.1.0, token ownership range = (510 , 10]
// node1 - ip = 127.0.1.1, token ownership range = (10 , 510]
List<Host> ring1 = TestTokenRange.makeRing(2, 1, 1, BigInteger.TEN, new BigInteger("1010"));
cp.setHosts(ring1);
LOG.info("testTokenToHostMappingInWrappedRange\n" + TestTokenRange.getRingDetails(ring1));
Operation<TestClient, String> op = new TokenTestOperation(BigInteger.ZERO);
RetryPolicy retryPolicy = new RunOnce();
OperationResult<String> result = cp.executeWithFailover(op, retryPolicy);
assertNotNull(result);
// since token ownership wraps node2 should own token 0
assertEquals("127.0.1.1",result.getHost().getIpAddress());
}
@Test
public void testTokenToHostMappingOutsideOfRing() throws ConnectionException {
ConnectionPool<TestClient> cp = createPool();
// the following will generate a ring of two nodes with the following characteristics;
// node1 - ip = 127.0.1.0, token ownership range = (500 , 0]
// node1 - ip = 127.0.1.1, token ownership range = (0 , 500]
List<Host> ring1 = TestTokenRange.makeRing(2, 1, 1, BigInteger.ZERO, new BigInteger("1000"));
cp.setHosts(ring1);
LOG.info("testTokenToHostMappingOutsideOfRing\n" + TestTokenRange.getRingDetails(ring1));
Operation<TestClient, String> op = new TokenTestOperation(new BigInteger("1250"));
RetryPolicy retryPolicy = new RunOnce();
OperationResult<String> result = cp.executeWithFailover(op, retryPolicy);
assertNotNull(result);
// requests for tokens outside the ring will be serviced by host associated with
// 1st partition in ring
assertEquals("127.0.1.1",result.getHost().getIpAddress());
}
@Test
public void changeRingTest() {
ConnectionPool<TestClient> cp = createPool();
List<Host> ring1 = makeRing(6, 3, 1);
List<Host> ring2 = makeRing(6, 3, 2);
cp.setHosts(ring1);
List<HostConnectionPool<TestClient>> hosts1 = cp.getActivePools();
cp.setHosts(ring2);
List<HostConnectionPool<TestClient>> hosts2 = cp.getActivePools();
LOG.info(hosts1.toString());
LOG.info(hosts2.toString());
}
private List<Host> makeRing(int nHosts, int replication_factor, int id) {
return TestTokenRange.makeRing(nHosts,replication_factor,id,TokenGenerator.MINIMUM,TokenGenerator.MAXIMUM);
}
}