views:

20

answers:

1

I wrote a simpe test to validate my own understanding of the thrift interface for Cassandra. It just inserts a row into the database (using the keyspace and column familty that come preconfigured with the cassandra installation), then reads it from the database and compares the results.

public class CassandraAPITest {
    @Test
    public void testCassandraAPI() throws Exception {
        TTransport tr = new TSocket("localhost", 9160);
        tr.open();
        Client client = new Cassandra.Client(new TBinaryProtocol(tr));
        String key = "123";
        byte[] value = { 52, 53, 54 };
        ColumnPath columnPath = new ColumnPath("Standard1");
        columnPath.setColumn("abc".getBytes("UTF8"));
        long timestamp = System.currentTimeMillis();

       client.insert("Keyspace1", key, columnPath, value, timestamp, ConsistencyLevel.ONE);

        SlicePredicate predicate = new SlicePredicate();
        SliceRange sliceRange = new SliceRange();
        sliceRange.setStart(new byte[0]);
        sliceRange.setFinish(new byte[0]);
        predicate.setSlice_range(sliceRange);

        List<ColumnOrSuperColumn> result = client.get_slice("Keyspace1", key, new ColumnParent("Standard1"), predicate, ConsistencyLevel.ONE);

        assertEquals(1, result.size());
        byte[] actual = result.get(0).column.value;
        assertArrayEquals(value, actual);

        // client.remove("Keyspace1", key, columnPath, System.currentTimeMillis(), ConsistencyLevel.ONE);

        tr.close();
    }
}

This test runs fine. Of course it leaves a row behind in the database. I could delete the row at the end of the test by uncommenting the client.remove statement above (this also works fine). But what I tried instead was deleting the row via the command-line interface:

cassandra> connect localhost/9160                   
Connected to: "Test Cluster" on localhost/9160
cassandra> get Keyspace1.Standard1['123']
=> (column=616263, value=456, timestamp=1287909211506)
Returned 1 results.
cassandra> del Keyspace1.Standard1['123']   
row removed.
cassandra> get Keyspace1.Standard1['123']
Returned 0 results.

The test fails afterwards. Inserting the row into the database seems to have no effect anymore, so the line assertEquals(1, result.size()) fails:

java.lang.AssertionError: expected:<1> but was:<0>
    at org.junit.Assert.fail(Assert.java:91)
    at org.junit.Assert.failNotEquals(Assert.java:618)
    at org.junit.Assert.assertEquals(Assert.java:126)
    at org.junit.Assert.assertEquals(Assert.java:443)
    at org.junit.Assert.assertEquals(Assert.java:427)
    at test.package.CassandraAPITest.testCassandraAPI(CassandraAPITest.java:48)

I don't get any error messages (neither on the client nor on the server) and I have no idea what the cause of the problem might be.

+2  A: 

You are inserting with millisecond resolution but the CLI (and other high level clients) uses microseconds. So your second insert is in the past, compared to the delete, so Cassandra correctly ignores it.

jbellis
I don't see how the different resolutions would make any difference. After running the UnitTest (which inserts the row ) I manually type in the deletion statements in the terminal window. Thereafter I switch to Eclipse again and rerun my tests. These manual tasks that happen between the execution of the statements all surely take more than a microsecond. Am I getting somthing wrong here?
sme
As an example to keep the numbers simple, say you do your original insert on Jan 1 1970, 00:01, your delete at 00:02, and your next insert at 00:03. So your first insert, System.currentTimeMillis() returns 1000. For the delete, microseconds returns 2000000. For the final insert, currentTimeMillis returns 3000. 3000 < 20000000 so Cassandra ignores that as an obsolete event.
jbellis
Also: you should really be using Hector from Java, instead of writing raw Thrift. http://github.com/rantav/hector
jbellis
Ah, got it now. Not so obvious behaviour though. Will take a look at Hector.
sme