package com.netflix.astyanax.contrib.dualwrites;
import com.netflix.astyanax.AstyanaxContext;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.connectionpool.NodeDiscoveryType;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl;
import com.netflix.astyanax.connectionpool.impl.ConnectionPoolType;
import com.netflix.astyanax.impl.AstyanaxConfigurationImpl;
import com.netflix.astyanax.model.ColumnFamily;
import com.netflix.astyanax.model.ColumnList;
import com.netflix.astyanax.model.ConsistencyLevel;
import com.netflix.astyanax.serializers.IntegerSerializer;
import com.netflix.astyanax.serializers.LongSerializer;
import com.netflix.astyanax.serializers.StringSerializer;
import com.netflix.astyanax.thrift.ThriftFamilyFactory;
public class DualWritesDemo {
final String cluster1 = "cass_dualwrites_source";
final String ks1 = "dualwritessrc";
final String seed1 = "";
final String cluster2 = "cass_dualwrites_dest";
final String ks2 = "dualwritessrc";
final String seed2 = "";
final ColumnFamily<Integer, Long> CF_DUAL_WRITES =
ColumnFamily.newColumnFamily("foobar", IntegerSerializer.get(), LongSerializer.get(), StringSerializer.get());
AstyanaxContext<Keyspace> ctx1;
Keyspace keyspace1;
AstyanaxContext<Keyspace> ctx2;
Keyspace keyspace2;
DualWritesKeyspace dualKeyspace = null;
FailedWritesLogger logger = new LogBasedFailedWritesLogger();
BestEffortSecondaryWriteStrategy execStrategy = new BestEffortSecondaryWriteStrategy(logger);
public DualWritesDemo() {
ctx1 = getKeyspaceContext(ks1, seed1);
keyspace1 = ctx1.getClient();
ctx2 = getKeyspaceContext(ks2, seed2);
keyspace2 = ctx2.getClient();
}
public void run() throws Exception {
try {
ctx1 = getKeyspaceContext(ks1, seed1);
keyspace1 = ctx1.getClient();
ctx1.start();
ctx2 = getKeyspaceContext(ks2, seed2);
keyspace2 = ctx2.getClient();
ctx2.start();
Thread.sleep(100);
logger.init();
DualKeyspaceMetadata dualKeyspaceSetup = new DualKeyspaceMetadata(cluster1, ks1, cluster2, ks2);
dualKeyspace = new DualWritesKeyspace(dualKeyspaceSetup, keyspace1, keyspace2, execStrategy);
addRowToKS(dualKeyspace, 1, 0, 10);
verifyPresent(keyspace1, 1);
verifyNotPresent(keyspace2, 1);
dualKeyspace.dualWritesEnabled();
addRowToKS(dualKeyspace, 2, 0, 10);
verifyPresent(keyspace1, 2);
verifyPresent(keyspace2, 2);
dualKeyspace.dualWritesDisabled();
addRowToKS(dualKeyspace, 3, 0, 10);
verifyPresent(keyspace1, 3);
verifyNotPresent(keyspace2, 3);
dualKeyspace.flipPrimaryAndSecondary();
addRowToKS(dualKeyspace, 4, 0, 10);
verifyNotPresent(keyspace1, 4);
verifyPresent(keyspace2, 4);
dualKeyspace.dualWritesEnabled();
addRowToKS(dualKeyspace, 5, 0, 10);
verifyPresent(keyspace1, 5);
verifyPresent(keyspace2, 5);
dualKeyspace.dualWritesDisabled();
addRowToKS(dualKeyspace, 6, 0, 10);
verifyNotPresent(keyspace1, 6);
verifyPresent(keyspace2, 6);
dualKeyspace.flipPrimaryAndSecondary();
addRowToKS(dualKeyspace, 7, 0, 10);
verifyPresent(keyspace1, 7);
verifyNotPresent(keyspace2, 7);
dualKeyspace.dualWritesEnabled();
addRowToKS(dualKeyspace, 8, 0, 10);
verifyPresent(keyspace1, 8);
verifyPresent(keyspace2, 8);
deleteRowFromKS(dualKeyspace, 1,2,3,4,5,6,7,8);
verifyNotPresent(keyspace1, 1,2,3,4,5,6,7,8);
verifyNotPresent(keyspace2, 1,2,3,4,5,6,7,8);
} finally {
if (ctx1 != null) {
ctx1.shutdown();
}
if (ctx2 != null) {
ctx2.shutdown();
}
}
}
private void addRowToKS(Keyspace ks, int rowKey, int start, int end) throws ConnectionException {
MutationBatch mb = ks.prepareMutationBatch();
for (long i=start; i<end; i++) {
mb.withRow(CF_DUAL_WRITES, rowKey).putColumn(i, "foo");
}
mb.execute();
}
private void deleteRowFromKS(Keyspace ks, int ... rowKeys) throws ConnectionException {
MutationBatch mb = ks.prepareMutationBatch();
for (int rowKey : rowKeys) {
mb.withRow(CF_DUAL_WRITES, rowKey).delete();
}
mb.execute();
}
private AstyanaxContext<Keyspace> getKeyspaceContext(final String ks, final String seedHost) {
AstyanaxContext<Keyspace> ctx =
new AstyanaxContext.Builder()
.forKeyspace(ks)
.withConnectionPoolConfiguration(
new ConnectionPoolConfigurationImpl("myCPConfig-" + ks)
.setSeeds(seedHost)
.setPort(7102))
.withAstyanaxConfiguration(
new AstyanaxConfigurationImpl()
.setDefaultReadConsistencyLevel(ConsistencyLevel.CL_LOCAL_QUORUM)
.setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE)
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE))
.buildKeyspace(ThriftFamilyFactory.getInstance());
return ctx;
}
private void verifyPresent(Keyspace ks, int rowKey) throws ConnectionException {
ColumnList<Long> result = ks.prepareQuery(CF_DUAL_WRITES).getRow(rowKey).execute().getResult();
if (result.isEmpty()) {
throw new RuntimeException("Row: " + rowKey + " missing from keysapce: " + ks.getKeyspaceName());
} else {
System.out.println("Verified Row: " + rowKey + " present in ks: " + ks.getKeyspaceName());
}
}
private void verifyNotPresent(Keyspace ks, int rowKey) throws ConnectionException {
ColumnList<Long> result = ks.prepareQuery(CF_DUAL_WRITES).getRow(rowKey).execute().getResult();
if (!result.isEmpty()) {
throw new RuntimeException("Row: " + rowKey + " present in keysapce: " + ks.getKeyspaceName());
} else {
System.out.println("Verified Row: " + rowKey + " NOT present in ks: " + ks.getKeyspaceName());
}
}
private void verifyNotPresent(Keyspace ks, int ... rowKeys) throws ConnectionException {
for (int rowKey : rowKeys) {
verifyNotPresent(ks, rowKey);
}
}
public static void main(String[] args) {
try {
new DualWritesDemo().run();
} catch (Exception e) {
e.printStackTrace();
}
}
}