package de.jbellmann.tomcat.cassandra.astyanax;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import com.netflix.astyanax.AstyanaxContext;
import com.netflix.astyanax.Cluster;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.MutationBatch;
import com.netflix.astyanax.connectionpool.NodeDiscoveryType;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl;
import com.netflix.astyanax.connectionpool.impl.Slf4jConnectionPoolMonitorImpl;
import com.netflix.astyanax.ddl.KeyspaceDefinition;
import com.netflix.astyanax.impl.AstyanaxConfigurationImpl;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.ColumnFamily;
import com.netflix.astyanax.model.ColumnList;
import com.netflix.astyanax.model.Row;
import com.netflix.astyanax.model.Rows;
//import com.netflix.astyanax.serializers.ObjectSerializer;
import com.netflix.astyanax.serializers.StringSerializer;
import com.netflix.astyanax.thrift.ThriftFamilyFactory;
import com.netflix.astyanax.util.RangeBuilder;
import de.jbellmann.tomcat.cassandra.CassandraTemplate;
/**
*
*
*
* @author Joerg Bellmann
*
*/
public class AstyanaxCassandraTemplate extends CassandraTemplate {
private final Log log = LogFactory.getLog(CassandraTemplate.class);
private AstyanaxContext<Cluster> context;
private Keyspace keyspace;
private ColumnFamily<String, Object> columnFamily;
private de.jbellmann.tomcat.cassandra.astyanax.ClassLoaderAwareObjectSerializer objectSerializer;
@Override
public void initialize(ClassLoader classLoader) {
objectSerializer = new de.jbellmann.tomcat.cassandra.astyanax.ClassLoaderAwareObjectSerializer(classLoader);
context = new AstyanaxContext.Builder()
.forCluster(getClusterName())
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl().setDiscoveryType(NodeDiscoveryType.NONE))
.withConnectionPoolConfiguration(
new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
.setMaxTimeoutCount(5)
.setConnectTimeout(10000))
.withConnectionPoolMonitor(new Slf4jConnectionPoolMonitorImpl())
.buildCluster(ThriftFamilyFactory.getInstance());
context.start();
try{
if(context.getEntity().describeKeyspace(getKeyspaceName()) == null){
KeyspaceDefinition ksDef = context.getEntity().makeKeyspaceDefinition();
Map<String, String> stratOptions = new HashMap<String, String>();
stratOptions.put("replication_factor", "1");
ksDef.setName(getKeyspaceName())
.setStrategyOptions(stratOptions)
.setStrategyClass(getStrategyClassName())
.addColumnFamily(
context.getEntity().makeColumnFamilyDefinition()
.setName(getColumnFamilyName())
.setComparatorType("BytesType")
.setKeyValidationClass("BytesType"));
context.getEntity().addKeyspace(ksDef);
}
}catch(Exception e){
log.error(e.getMessage(), e);
}
keyspace = context.getEntity().getKeyspace(getKeyspaceName());
// in hector we set the classloader to the objectSerializer
columnFamily = new ColumnFamily<String, Object>(getColumnFamilyName(), StringSerializer.get(), objectSerializer);
}
@Override
public void shutdown() {
log.info("Shuttingdown context ...");
context.shutdown();
log.info("Context is down");
}
@Override
public long getCreationTime(final String sessionId) {
log.info("Get CREATION_TIME for Session : " + sessionId);
try {
OperationResult<ColumnList<Object>> result = keyspace.prepareQuery(columnFamily).getKey(sessionId).execute();
Column<Object> column = result.getResult().getColumnByName(CREATIONTIME_COLUMN_NAME);
return column != null ? column.getLongValue() : -1;
} catch (ConnectionException e) {
log.error("Could not get 'creationTime' because of 'ConnectionException'", e);
throw new RuntimeException(e);
}
}
@Override
public void setCreationTime(final String sessionId, final long time) {
log.info("Set CREATION_TIME for Session : " + sessionId + " to value " + time);
MutationBatch mutation = keyspace.prepareMutationBatch();
mutation.withRow(columnFamily, sessionId).putColumn(CREATIONTIME_COLUMN_NAME, time, null);
try{
mutation.execute();
}catch(ConnectionException e){
log.error("Could not insert 'creationTime' for sessionId " + sessionId, e);
throw new RuntimeException(e);
}
}
@Override
public long getLastAccessedTime(final String sessionId) {
log.info("Get LAST_ACCESSED_TIME for Session : " + sessionId);
try {
OperationResult<ColumnList<Object>> result = keyspace.prepareQuery(columnFamily).getKey(sessionId).execute();
Column<Object> column = result.getResult().getColumnByName(LAST_ACCESSTIME_COLUMN_NAME);
return column != null ? column.getLongValue() : -1;
} catch (ConnectionException e) {
log.error("Could not get 'creationTime' because of 'ConnectionException'", e);
throw new RuntimeException(e);
}
}
@Override
public void setLastAccessedTime(final String sessionId, final long time) {
log.info("Set LAST_ACCESSED_TIME for Session : " + sessionId + " to value " + time);
MutationBatch mutation = keyspace.prepareMutationBatch();
mutation.withRow(columnFamily, sessionId).putColumn(LAST_ACCESSTIME_COLUMN_NAME, time, null);
try{
mutation.execute();
}catch(ConnectionException e){
log.error("Could not insert 'lastAccessTime' for sessionId " + sessionId, e);
throw new RuntimeException(e);
}
}
@Override
public Object getAttribute(final String sessionId, final String name) {
log.info("Get attribute '" + name + "' for Session : " + sessionId);
try {
OperationResult<ColumnList<Object>> result = keyspace.prepareQuery(columnFamily).getKey(sessionId).execute();
Column<Object> column = result.getResult().getColumnByName(name);
return column != null ? column.getValue(objectSerializer) : null;
} catch (ConnectionException e) {
log.error("Could not get 'creationTime' because of 'ConnectionException'", e);
throw new RuntimeException(e);
}
}
@Override
public void setAttribute(final String sessionId, final String name, final Object value) {
log.info("Set attribute '" + name + "' with value " + value.toString() + " for Session : " + sessionId + "");
MutationBatch mutation = keyspace.prepareMutationBatch();
mutation.withRow(columnFamily, sessionId).putColumn(name, value, objectSerializer, null);
try{
mutation.execute();
}catch(ConnectionException e){
log.error("Could not 'setAttribute' for column with name: '"+ name+ "' for sessionId " + sessionId, e);
throw new RuntimeException(e);
}
}
@Override
public void removeAttribute(final String sessionId, final String name) {
log.info("Remove attribute '" + name + "' for Session : " + sessionId);
MutationBatch mutation = keyspace.prepareMutationBatch();
mutation.withRow(columnFamily, sessionId).deleteColumn(name);
try{
mutation.execute();
}catch(ConnectionException e){
log.error("Could not delete column '" + name + "' for sessionId " + sessionId, e);
throw new RuntimeException(e);
}
}
@Override
public String[] keys(final String sessionId) {
List<String> resultList = new ArrayList<String>();
ColumnList<Object> columnList = null;
try {
columnList = keyspace.prepareQuery(columnFamily).getKey(sessionId).execute().getResult();
} catch (ConnectionException e) {
log.error("Could not get all column names for session " + sessionId);
throw new RuntimeException(e);
}
for(Column<Object> column : columnList){
resultList.add(column.getName().toString());
}
return resultList.toArray(new String[resultList.size()]);
}
@Override
public Enumeration<String> getAttributeNames(String sessionId) {
return Collections.enumeration(Arrays.asList(keys(sessionId)));
}
@Override
public List<String> findSessionKeys() {
List<String> resultList = new ArrayList<String>();
Rows<String, Object> result;
try {
result = keyspace.prepareQuery(columnFamily)
.getAllRows()
.withColumnRange(new RangeBuilder().setLimit(0).build())
.execute().getResult();
} catch (ConnectionException e) {
log.error("Could not get the keys for all rows", e);
throw new RuntimeException(e);
}
for(Row<String,Object> row : result){
resultList.add(row.getKey());
}
return resultList;
}
@Override
public void removeSession(final String sessionId) {
MutationBatch mutation = keyspace.prepareMutationBatch();
mutation.withRow(columnFamily, sessionId).delete();
try{
mutation.execute();
}catch(ConnectionException e){
log.error("Could not delete row for sessionId '" + sessionId, e);
throw new RuntimeException(e);
}
}
}