package io.teknek.intravert.action.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.ConsistencyLevel; import org.apache.cassandra.db.IMutation; import org.apache.cassandra.db.RowMutation; import org.apache.cassandra.db.filter.QueryPath; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.exceptions.InvalidRequestException; import org.apache.cassandra.exceptions.OverloadedException; import org.apache.cassandra.exceptions.UnavailableException; import org.apache.cassandra.exceptions.WriteTimeoutException; import org.apache.cassandra.service.MigrationManager; import org.apache.cassandra.service.StorageProxy; import org.apache.cassandra.thrift.CfDef; import org.apache.cassandra.utils.ByteBufferUtil; import io.teknek.intravert.action.Action; import io.teknek.intravert.action.filter.Filter; import io.teknek.intravert.action.filter.FilterFactory; import io.teknek.intravert.model.Constants; import io.teknek.intravert.model.Operation; import io.teknek.intravert.model.Response; import io.teknek.intravert.service.ApplicationContext; import io.teknek.intravert.service.RequestContext; import io.teknek.nit.NitDesc; import io.teknek.nit.NitException; public class CreateFilterAction implements Action { public static final String IV_KEYSPACE = "intravert"; public static final String FILTER_CF = "filter"; @Override public void doAction(Operation operation, Response response, RequestContext request, ApplicationContext application) { String name = (String) operation.getArguments().get("name"); String scope = (String) operation.getArguments().get("scope"); NitDesc n = new NitDesc(); n.setSpec(NitDesc.NitSpec.valueOf((String) operation.getArguments().get("spec"))); n.setTheClass((String) operation.getArguments().get("theClass")); n.setScript((String) operation.getArguments().get("script")); try { Filter f = FilterFactory.createFilter(io.teknek.nit.NitFactory.construct(n)); if ("session".equalsIgnoreCase(scope)){ request.getSession().putFilter(name, f); } else if ("application".equalsIgnoreCase(scope)){ addFilterToCluster(f, n, name); application.putFilter(name, f); } } catch (NitException | WriteTimeoutException | InvalidRequestException | ConfigurationException | UnavailableException | OverloadedException e) { throw new RuntimeException(e); } Map m = new HashMap(); m.put(Constants.RESULT, Constants.OK); response.getResults().put(operation.getId(), Arrays.asList(m)); } public void maybeCreateColumnFamily() throws InvalidRequestException, ConfigurationException { List<String> keyspaces = Schema.instance.getNonSystemTables(); if (!keyspaces.contains(IV_KEYSPACE)){ CreateKeyspaceAction.createKeyspace(IV_KEYSPACE, 1); CFMetaData cfm = null; CfDef def = new CfDef(); def.setKeyspace(IV_KEYSPACE); def.setName(FILTER_CF); cfm = CFMetaData.fromThrift(def); cfm.addDefaultIndexNames(); MigrationManager.announceNewColumnFamily(cfm); } } public void addFilterToCluster(Filter f, NitDesc n, String name) throws InvalidRequestException, ConfigurationException, WriteTimeoutException, UnavailableException, OverloadedException{ maybeCreateColumnFamily(); List<IMutation> changes = new ArrayList<>(); { RowMutation rm = new RowMutation(IV_KEYSPACE, ByteBufferUtil.bytes(name)); QueryPath qp = new QueryPath(FILTER_CF, null, ByteBufferUtil.bytes("spec")); rm.add(qp, ByteBufferUtil.bytes(n.getSpec().toString()), System.nanoTime()); changes.add(rm); } { RowMutation rm = new RowMutation(IV_KEYSPACE, ByteBufferUtil.bytes(name)); QueryPath qp = new QueryPath(FILTER_CF, null, ByteBufferUtil.bytes("theClass")); String cs = n.getTheClass() == null ? "" : n.getTheClass(); rm.add(qp, ByteBufferUtil.bytes(cs), System.nanoTime()); changes.add(rm); } { RowMutation rm = new RowMutation(IV_KEYSPACE, ByteBufferUtil.bytes(name)); QueryPath qp = new QueryPath(FILTER_CF, null, ByteBufferUtil.bytes("script")); String cs = n.getScript() == null ? "" : n.getScript(); rm.add(qp, ByteBufferUtil.bytes(cs), System.nanoTime()); changes.add(rm); } StorageProxy.mutate(changes, ConsistencyLevel.QUORUM); } }