You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ty...@apache.org on 2015/11/13 22:36:25 UTC

cassandra git commit: Preserve deletion info when notifying 2ary index of row update

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 5730e7b9f -> c2320c92f


Preserve deletion info when notifying 2ary index of row update

Patch by Tyler Hobbs; reviewed by Sam Tunnicliffe for CASSANDRA-10694


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c2320c92
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c2320c92
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c2320c92

Branch: refs/heads/cassandra-3.0
Commit: c2320c92fdae6815b8952ba98b1e8e5239b5be2a
Parents: 5730e7b
Author: Tyler Hobbs <ty...@gmail.com>
Authored: Fri Nov 13 15:35:40 2015 -0600
Committer: Tyler Hobbs <ty...@gmail.com>
Committed: Fri Nov 13 15:35:40 2015 -0600

----------------------------------------------------------------------
 CHANGES.txt                                     |  2 +
 .../cassandra/index/SecondaryIndexManager.java  |  6 ++-
 .../validation/entities/SecondaryIndexTest.java | 55 ++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2320c92/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index f214200..8bb67e1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,6 @@
 3.0.1
+ * Correctly preserve deletion info on updated rows when notifying indexers
+   of single-row deletions (CASSANDRA-10694)
  * Notify indexers of partition delete during cleanup (CASSANDRA-10685)
  * Keep the file open in trySkipCache (CASSANDRA-10669)
  * Updated trigger example (CASSANDRA-10257)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2320c92/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/index/SecondaryIndexManager.java b/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
index db53c25..df8e38d 100644
--- a/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
+++ b/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
@@ -273,7 +273,7 @@ public class SecondaryIndexManager implements IndexRegistry
     /**
      * Checks if the specified {@link ColumnFamilyStore} is the one secondary index.
      *
-     * @param cfs the name of the <code>ColumnFamilyStore</code> to check.
+     * @param cfName the name of the <code>ColumnFamilyStore</code> to check.
      * @return <code>true</code> if the specified <code>ColumnFamilyStore</code> is a secondary index,
      * <code>false</code> otherwise.
      */
@@ -309,7 +309,7 @@ public class SecondaryIndexManager implements IndexRegistry
     /**
      * Returns the index name
      *
-     * @param cfName the <code>ColumnFamilyStore</code> name
+     * @param cfs the <code>ColumnFamilyStore</code>
      * @return the index name
      */
     public static String getIndexName(ColumnFamilyStore cfs)
@@ -775,9 +775,11 @@ public class SecondaryIndexManager implements IndexRegistry
             final Row.Builder toRemove = BTreeRow.sortedBuilder();
             toRemove.newRow(existing.clustering());
             toRemove.addPrimaryKeyLivenessInfo(existing.primaryKeyLivenessInfo());
+            toRemove.addRowDeletion(existing.deletion());
             final Row.Builder toInsert = BTreeRow.sortedBuilder();
             toInsert.newRow(updated.clustering());
             toInsert.addPrimaryKeyLivenessInfo(updated.primaryKeyLivenessInfo());
+            toInsert.addRowDeletion(updated.deletion());
             // diff listener collates the columns to be added & removed from the indexes
             RowDiffListener diffListener = new RowDiffListener()
             {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2320c92/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
index 9cba01a..225e197 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java
@@ -20,6 +20,8 @@ package org.apache.cassandra.cql3.validation.entities;
 import java.nio.ByteBuffer;
 import java.util.*;
 
+import org.apache.cassandra.db.DeletionTime;
+import org.apache.cassandra.utils.Pair;
 import org.apache.commons.lang3.StringUtils;
 import org.junit.Test;
 
@@ -785,6 +787,59 @@ public class SecondaryIndexTest extends CQLTester
     }
 
     @Test
+    public void testDeletions() throws Throwable
+    {
+        // Test for bugs like CASSANDRA-10694.  These may not be readily visible with the built-in secondary index
+        // implementation because of the stale entry handling.
+
+        String indexClassName = StubIndex.class.getName();
+        createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY ((a), b))");
+        createIndex(String.format("CREATE CUSTOM INDEX c_idx ON %%s(c) USING '%s'", indexClassName));
+
+        ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
+        CFMetaData cfm = cfs.metadata;
+        StubIndex index1 = (StubIndex) cfs.indexManager.getIndex(cfm.getIndexes()
+                .get("c_idx")
+                .orElseThrow(throwAssert("index not found")));
+
+        execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?) USING TIMESTAMP 1", 0, 0, 0);
+        assertEquals(1, index1.rowsInserted.size());
+
+        execute("DELETE FROM %s USING TIMESTAMP 2 WHERE a = ? AND b = ?", 0, 0);
+        assertEquals(1, index1.rowsUpdated.size());
+        Pair<Row, Row> update = index1.rowsUpdated.get(0);
+        Row existingRow = update.left;
+        Row newRow = update.right;
+
+        // check the existing row from the update call
+        assertTrue(existingRow.deletion().isLive());
+        assertEquals(DeletionTime.LIVE, existingRow.deletion().time());
+        assertEquals(1L, existingRow.primaryKeyLivenessInfo().timestamp());
+
+        // check the new row from the update call
+        assertFalse(newRow.deletion().isLive());
+        assertEquals(2L, newRow.deletion().time().markedForDeleteAt());
+        assertFalse(newRow.cells().iterator().hasNext());
+
+        // delete the same row again
+        execute("DELETE FROM %s USING TIMESTAMP 3 WHERE a = ? AND b = ?", 0, 0);
+        assertEquals(2, index1.rowsUpdated.size());
+        update = index1.rowsUpdated.get(1);
+        existingRow = update.left;
+        newRow = update.right;
+
+        // check the new row from the update call
+        assertFalse(existingRow.deletion().isLive());
+        assertEquals(2L, existingRow.deletion().time().markedForDeleteAt());
+        assertFalse(existingRow.cells().iterator().hasNext());
+
+        // check the new row from the update call
+        assertFalse(newRow.deletion().isLive());
+        assertEquals(3L, newRow.deletion().time().markedForDeleteAt());
+        assertFalse(newRow.cells().iterator().hasNext());
+    }
+
+    @Test
     public void testUpdatesToMemtableData() throws Throwable
     {
         // verify the contract specified by Index.Indexer::updateRow(oldRowData, newRowData),