package com.voxeo.moho.reg.impl.cassandra;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import me.prettyprint.cassandra.serializers.ObjectSerializer;
import me.prettyprint.cassandra.serializers.StringSerializer;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.Keyspace;
import me.prettyprint.hector.api.beans.ColumnSlice;
import me.prettyprint.hector.api.beans.HColumn;
import me.prettyprint.hector.api.factory.HFactory;
import me.prettyprint.hector.api.mutation.Mutator;
import me.prettyprint.hector.api.query.ColumnQuery;
import me.prettyprint.hector.api.query.CountQuery;
import me.prettyprint.hector.api.query.QueryResult;
import me.prettyprint.hector.api.query.SliceQuery;
import com.voxeo.moho.Endpoint;
import com.voxeo.moho.event.RegisterEvent.Contact;
public class CassandraRegisterStore extends NoSqlDatabaseRegisterStore {
private static final ObjectSerializer OBJECT_SERIALIZER = ObjectSerializer.get();
private static final StringSerializer STRING_SERIALIZER = StringSerializer.get();
private static final String DEFAULT_DATABASE_ADDRESS = "localhost:9160";
private static final String DEFAULT_CLUSTER_NAME = "MohoCluster";
private static final String DEFAULT_KEYSPACE_NAME = "Registrar";
private static final String DEFAULT_COLUMN_FAMILY_NAME = "Bindings";
private Cluster _cluster;
private Keyspace _keyspace;
@Override
public void init(Map<String, String> props) {
String databaseAddress = props.get("databaseAddress");
String clusterName = props.get("clusterName");
String keySapceName = props.get("keysapceName");
_cluster = HFactory.getOrCreateCluster(clusterName != null ? clusterName : DEFAULT_CLUSTER_NAME, databaseAddress != null ? databaseAddress : DEFAULT_DATABASE_ADDRESS);
_keyspace = HFactory.createKeyspace(keySapceName != null ? keySapceName : DEFAULT_KEYSPACE_NAME, _cluster);
}
@Override
public void add(Endpoint addr, Contact contact) {
insertContact(addr, contact);
}
@Override
public void update(Endpoint addr, Contact contact) {
insertContact(addr, contact);
}
private Mutator<String> getMutator() {
return HFactory.createMutator(_keyspace, STRING_SERIALIZER);
}
private void insertContact(Endpoint addr, Contact contact) {
Mutator<String> mutator = getMutator();
mutator.addInsertion(getCleanUri(addr), DEFAULT_COLUMN_FAMILY_NAME, HFactory.createColumn(contact.getEndpoint().getURI().toString(), contact, STRING_SERIALIZER, OBJECT_SERIALIZER));
mutator.execute();
}
@Override
public void remove(Endpoint addr, Contact contact) {
Mutator<String> mutator = getMutator();
mutator.addDeletion(getCleanUri(addr), DEFAULT_COLUMN_FAMILY_NAME, contact.getEndpoint().getURI().toString(), STRING_SERIALIZER);
mutator.execute();
}
@Override
public void remove(Endpoint addr) {
Mutator<String> mutator = getMutator();
mutator.addDeletion(getCleanUri(addr), DEFAULT_COLUMN_FAMILY_NAME);
mutator.execute();
}
@Override
public Collection<Contact> getContacts(Endpoint addr) {
Collection<Contact> contacts = new ArrayList<Contact>();
List<HColumn<String, Object>> columns = querySliceResult(addr).getColumns();
for (HColumn<String, Object> hcolumn : columns) {
contacts.add((Contact) hcolumn.getValue());
}
return contacts;
}
@Override
public Iterator<Endpoint> getEndpoints() {
return null;
}
@Override
public Contact getContact(Endpoint addr, Endpoint contact) {
HColumn<String, Object> result = queryResult(addr, contact);
if (result == null) {
return null;
}
return (Contact) result.getValue();
}
@Override
public boolean isExisting(Endpoint addr, Contact contact) {
// CountQuery<String, Object> query = HFactory.createCountQuery(_keyspace, STRING_SERIALIZER, OBJECT_SERIALIZER);
// query.setColumnFamily(DEFAULT_COLUMN_FAMILY_NAME);
// query.setKey(getCleanUri(addr));
// query.setRange(contact.getEndpoint().getURI().toString(), contact.getEndpoint().getURI().toString(), 1);
// QueryResult<Integer> execute = query.execute();
// return execute.get().intValue() > 0;
return queryResult(addr, contact.getEndpoint()) != null;
}
private HColumn<String, Object> queryResult(Endpoint addr, Endpoint contact) {
ColumnQuery<String, String, Object> createColumnQuery = HFactory.createColumnQuery(_keyspace, STRING_SERIALIZER, STRING_SERIALIZER, OBJECT_SERIALIZER);
createColumnQuery.setColumnFamily(DEFAULT_COLUMN_FAMILY_NAME);
createColumnQuery.setKey(getCleanUri(addr));
createColumnQuery.setName(contact.getURI().toString());
QueryResult<HColumn<String, Object>> queryResult = createColumnQuery.execute();
return queryResult.get();
}
private String getCleanUri(Endpoint addr) {
String aor = addr.getURI().toString();
return deparameterize(aor);
}
private String deparameterize(String aor) {
return aor;
}
@Override
public boolean isExisting(Endpoint addr) {
return querySliceResult(addr).getColumns().size() > 0;
}
private ColumnSlice<String, Object> querySliceResult(Endpoint addr) {
SliceQuery<String, String, Object> createSliceQuery = HFactory.createSliceQuery(_keyspace, STRING_SERIALIZER, STRING_SERIALIZER, OBJECT_SERIALIZER);
createSliceQuery.setColumnFamily(DEFAULT_COLUMN_FAMILY_NAME);
createSliceQuery.setKey(getCleanUri(addr));
createSliceQuery.setColumnNames("", "");
createSliceQuery.setRange("", "", false, Integer.MAX_VALUE);
QueryResult<ColumnSlice<String, Object>> execute = createSliceQuery.execute();
ColumnSlice<String, Object> columnSlice = execute.get();
return columnSlice;
}
@Override
public void destroy() {
_cluster.getConnectionManager().shutdown();
HFactory.shutdownCluster(_cluster);
_keyspace = null;
_cluster = null;
}
}