Skip to content

Commit 8733de6

Browse files
author
Sylvain Lebresne
committed
Followup for CASSANDRA-7403
1 parent 0bc4663 commit 8733de6

File tree

4 files changed

+23
-21
lines changed

4 files changed

+23
-21
lines changed

src/java/org/apache/cassandra/db/BufferExpiringCell.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public void validateFields(CFMetaData metadata) throws MarshalException
142142
throw new MarshalException("The local expiration time should not be negative");
143143
}
144144

145+
@Override
145146
public Cell reconcile(Cell cell)
146147
{
147148
long ts1 = timestamp(), ts2 = cell.timestamp();
@@ -150,11 +151,10 @@ public Cell reconcile(Cell cell)
150151
// we should prefer tombstones
151152
if (cell instanceof DeletedCell)
152153
return cell;
153-
// however if we're both ExpiringCells, we should prefer the one with the longest ttl
154-
// (really in preference _always_ to the value comparison)
155154
int c = value().compareTo(cell.value());
156155
if (c != 0)
157156
return c < 0 ? cell : this;
157+
// If we have same timestamp and value, prefer the longest ttl
158158
if (cell instanceof ExpiringCell)
159159
{
160160
int let1 = localExpirationTime, let2 = cell.getLocalDeletionTime();

src/java/org/apache/cassandra/db/NativeExpiringCell.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public void updateDigest(MessageDigest digest)
128128
FBUtilities.updateWithInt(digest, getTimeToLive());
129129
}
130130

131+
@Override
131132
public Cell reconcile(Cell cell)
132133
{
133134
long ts1 = timestamp(), ts2 = cell.timestamp();
@@ -136,11 +137,10 @@ public Cell reconcile(Cell cell)
136137
// we should prefer tombstones
137138
if (cell instanceof DeletedCell)
138139
return cell;
139-
// however if we're both ExpiringCells, we should prefer the one with the longest ttl
140-
// (really in preference _always_ to the value comparison)
141140
int c = value().compareTo(cell.value());
142141
if (c != 0)
143142
return c < 0 ? cell : this;
143+
// If we have same timestamp and value, prefer the longest ttl
144144
if (cell instanceof ExpiringCell)
145145
{
146146
int let1 = getLocalDeletionTime(), let2 = cell.getLocalDeletionTime();

src/java/org/apache/cassandra/db/index/AbstractSimplePerColumnSecondaryIndex.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,12 @@ public void insert(ByteBuffer rowKey, Cell cell, OpOrder.Group opGroup)
121121
}
122122

123123
public void update(ByteBuffer rowKey, Cell oldCol, Cell col, OpOrder.Group opGroup)
124-
{
124+
{
125125
// insert the new value before removing the old one, so we never have a period
126126
// where the row is invisible to both queries (the opposite seems preferable); see CASSANDRA-5540
127127
insert(rowKey, col, opGroup);
128-
delete(rowKey, oldCol, opGroup);
128+
if (SecondaryIndexManager.shouldCleanupOldValue(oldCol, col))
129+
delete(rowKey, oldCol, opGroup);
129130
}
130131

131132
public void removeIndex(ByteBuffer columnName)

src/java/org/apache/cassandra/db/index/SecondaryIndexManager.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,22 @@ public boolean validate(Cell cell)
620620
return true;
621621
}
622622

623+
static boolean shouldCleanupOldValue(Cell oldCell, Cell newCell)
624+
{
625+
// If any one of name/value/timestamp are different, then we
626+
// should delete from the index. If not, then we can infer that
627+
// at least one of the cells is an ExpiringColumn and that the
628+
// difference is in the expiry time. In this case, we don't want to
629+
// delete the old value from the index as the tombstone we insert
630+
// will just hide the inserted value.
631+
// Completely identical cells (including expiring columns with
632+
// identical ttl & localExpirationTime) will not get this far due
633+
// to the oldCell.equals(newColumn) in StandardUpdater.update
634+
return !oldCell.name().equals(newCell.name())
635+
|| !oldCell.value().equals(newCell.value())
636+
|| oldCell.timestamp() != newCell.timestamp();
637+
}
638+
623639
public static interface Updater
624640
{
625641
/** called when constructing the index against pre-existing data */
@@ -744,20 +760,5 @@ public void updateRowLevelIndexes()
744760
((PerRowSecondaryIndex) index).index(key.getKey(), cf);
745761
}
746762

747-
private boolean shouldCleanupOldValue(Cell oldCell, Cell newCell)
748-
{
749-
// If any one of name/value/timestamp are different, then we
750-
// should delete from the index. If not, then we can infer that
751-
// at least one of the cells is an ExpiringColumn and that the
752-
// difference is in the expiry time. In this case, we don't want to
753-
// delete the old value from the index as the tombstone we insert
754-
// will just hide the inserted value.
755-
// Completely identical cells (including expiring columns with
756-
// identical ttl & localExpirationTime) will not get this far due
757-
// to the oldCell.equals(newColumn) in StandardUpdater.update
758-
return !oldCell.name().equals(newCell.name())
759-
|| !oldCell.value().equals(newCell.value())
760-
|| oldCell.timestamp() != newCell.timestamp();
761-
}
762763
}
763764
}

0 commit comments

Comments
 (0)