mirror of https://github.com/apache/cassandra
Updated trigger example
patch by Mike Adamson; reviewed by Aleksey Yeschenko for CASSANDRA-10257
This commit is contained in:
parent
d766f4fb20
commit
fb463c79e0
|
|
@ -1,4 +1,5 @@
|
||||||
3.0.1
|
3.0.1
|
||||||
|
* Updated trigger example (CASSANDRA-10257)
|
||||||
Merged from 2.2:
|
Merged from 2.2:
|
||||||
* (Hadoop) ensure that Cluster instances are always closed (CASSANDRA-10058)
|
* (Hadoop) ensure that Cluster instances are always closed (CASSANDRA-10058)
|
||||||
Merged from 2.1:
|
Merged from 2.1:
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
Cassandra Trigger's Example:
|
Cassandra Trigger Example:
|
||||||
=========================
|
==========================
|
||||||
|
|
||||||
InvertedIndex class will create a inverted index of
|
The AuditTrigger class will create a basic audit of
|
||||||
RowKey:ColumnName:Value to Value:ColumnName:RowKey
|
activity on a table.
|
||||||
|
|
||||||
NOTE: This example is limited to append-only workloads,
|
|
||||||
doesn't delete indexes on deletes.
|
|
||||||
|
|
||||||
Installation:
|
Installation:
|
||||||
============
|
============
|
||||||
|
|
@ -13,9 +10,27 @@ change directory to <cassandra_src_dir>/examples/triggers
|
||||||
run "ant jar"
|
run "ant jar"
|
||||||
Copy build/trigger-example.jar to <cassandra_conf>/triggers/
|
Copy build/trigger-example.jar to <cassandra_conf>/triggers/
|
||||||
Copy conf/* to <cassandra_home>/conf/
|
Copy conf/* to <cassandra_home>/conf/
|
||||||
Create column family configured in InvertedIndex.properties
|
|
||||||
Example: Keyspace1.InvertedIndex as configured in InvertedIndex.properties
|
Create the keyspace and table configured in AuditTrigger.properties:
|
||||||
Configure trigger on the table.
|
CREATE KEYSPACE test WITH REPLICATION =
|
||||||
Example: CREATE TRIGGER test1 ON "Keyspace1"."Standard1"
|
{ 'class' : 'SimpleStrategy', 'replication_factor' : '1' };
|
||||||
USING 'org.apache.cassandra.triggers.InvertedIndex';
|
CREATE TABLE test.audit (key timeuuid, keyspace_name text,
|
||||||
Start inserting data to the column family which has the triggers.
|
table_name text, primary_key text, PRIMARY KEY(key));
|
||||||
|
|
||||||
|
Create a table to add the trigger to:
|
||||||
|
CREATE TABLE test.test (key text, value text, PRIMARY KEY(key));
|
||||||
|
Note: The example currently only handles non-composite partition keys
|
||||||
|
|
||||||
|
Configure the trigger on the table:
|
||||||
|
CREATE TRIGGER test1 ON test.test
|
||||||
|
USING 'org.apache.cassandra.triggers.AuditTrigger';
|
||||||
|
|
||||||
|
Start inserting data to the table that has the trigger. For each
|
||||||
|
partition added to the table an entry should appear in the 'audit' table:
|
||||||
|
INSERT INTO test.test (key, value) values ('1', '1');
|
||||||
|
SELECT * FROM test.audit;
|
||||||
|
|
||||||
|
key | keyspace_name | primary_key | table_name
|
||||||
|
--------------------------------------+---------------+-------------+------------
|
||||||
|
7dc75b60-770f-11e5-9019-033d8af33e6f | test | 1 | test
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,5 @@
|
||||||
# specific language governing permissions and limitations
|
# specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
keyspace=Keyspace1
|
keyspace=test
|
||||||
table=InvertedIndex
|
table=audit
|
||||||
|
|
@ -18,49 +18,42 @@
|
||||||
package org.apache.cassandra.triggers;
|
package org.apache.cassandra.triggers;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.Collections;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.apache.cassandra.config.Schema;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import org.apache.cassandra.db.Cell;
|
|
||||||
import org.apache.cassandra.db.ColumnFamily;
|
|
||||||
import org.apache.cassandra.db.Mutation;
|
import org.apache.cassandra.db.Mutation;
|
||||||
|
import org.apache.cassandra.db.RowUpdateBuilder;
|
||||||
|
import org.apache.cassandra.db.partitions.Partition;
|
||||||
import org.apache.cassandra.io.util.FileUtils;
|
import org.apache.cassandra.io.util.FileUtils;
|
||||||
|
import org.apache.cassandra.utils.FBUtilities;
|
||||||
|
import org.apache.cassandra.utils.UUIDGen;
|
||||||
|
|
||||||
public class InvertedIndex implements ITrigger
|
public class AuditTrigger implements ITrigger
|
||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(InvertedIndex.class);
|
|
||||||
private Properties properties = loadProperties();
|
private Properties properties = loadProperties();
|
||||||
|
|
||||||
public Collection<Mutation> augment(ByteBuffer key, ColumnFamily update)
|
public Collection<Mutation> augment(Partition update)
|
||||||
{
|
{
|
||||||
List<Mutation> mutations = new ArrayList<>(update.getColumnCount());
|
String auditKeyspace = properties.getProperty("keyspace");
|
||||||
|
String auditTable = properties.getProperty("table");
|
||||||
|
|
||||||
String indexKeySpace = properties.getProperty("keyspace");
|
RowUpdateBuilder audit = new RowUpdateBuilder(Schema.instance.getCFMetaData(auditKeyspace, auditTable),
|
||||||
String indexColumnFamily = properties.getProperty("table");
|
FBUtilities.timestampMicros(),
|
||||||
for (Cell cell : update)
|
UUIDGen.getTimeUUID());
|
||||||
{
|
|
||||||
// Skip the row marker and other empty values, since they lead to an empty key.
|
|
||||||
if (cell.value().remaining() > 0)
|
|
||||||
{
|
|
||||||
Mutation mutation = new Mutation(indexKeySpace, cell.value());
|
|
||||||
mutation.add(indexColumnFamily, cell.name(), key, System.currentTimeMillis());
|
|
||||||
mutations.add(mutation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mutations;
|
audit.add("keyspace_name", update.metadata().ksName);
|
||||||
|
audit.add("table_name", update.metadata().cfName);
|
||||||
|
audit.add("primary_key", update.metadata().getKeyValidator().getString(update.partitionKey().getKey()));
|
||||||
|
|
||||||
|
return Collections.singletonList(audit.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Properties loadProperties()
|
private static Properties loadProperties()
|
||||||
{
|
{
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
InputStream stream = InvertedIndex.class.getClassLoader().getResourceAsStream("InvertedIndex.properties");
|
InputStream stream = AuditTrigger.class.getClassLoader().getResourceAsStream("AuditTrigger.properties");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
properties.load(stream);
|
properties.load(stream);
|
||||||
|
|
@ -73,7 +66,6 @@ public class InvertedIndex implements ITrigger
|
||||||
{
|
{
|
||||||
FileUtils.closeQuietly(stream);
|
FileUtils.closeQuietly(stream);
|
||||||
}
|
}
|
||||||
logger.info("loaded property file, InvertedIndex.properties");
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue