Fix row size miscalculation in LazilyCompactedRow

when RangeTombstone is involved.
patch by yukim; reviewed by jbellis for CASSANDRA-7543
This commit is contained in:
Yuki Morishita 2014-07-16 15:57:31 -05:00
parent 0d90b03a30
commit 192596ad75
4 changed files with 68 additions and 7 deletions

View File

@ -1,6 +1,7 @@
1.2.19
* Set correct stream ID on responses when non-Exception Throwables
are thrown while handling native protocol messages (CASSANDRA-7470)
* Fix row size miscalculation in LazilyCompactedRow (CASSANDRA-7543)
1.2.18
* Support Thrift tables clustering columns on CqlPagingInputFormat (CASSANDRA-7445)

View File

@ -64,6 +64,7 @@ public class ColumnIndex
private final RangeTombstone.Tracker tombstoneTracker;
private final OnDiskAtom.Serializer atomSerializer;
private int atomCount;
private long openedMarkerSize = 0;
public Builder(ColumnFamily cf,
ByteBuffer key,
@ -159,7 +160,11 @@ public class ColumnIndex
startPosition = endPosition;
// TODO: have that use the firstColumn as min + make sure we optimize that on read
if (tombstoneTracker != null)
endPosition += tombstoneTracker.writeOpenedMarker(firstColumn, output, atomSerializer);
{
long tombstoneSize = tombstoneTracker.writeOpenedMarker(firstColumn, output, atomSerializer);
endPosition += tombstoneSize;
openedMarkerSize += tombstoneSize;
}
blockSize = 0; // We don't count repeated tombstone marker in the block size, to avoid a situation
// where we wouldn't make any progress because a block is filled by said marker
}
@ -204,5 +209,10 @@ public class ColumnIndex
assert result.columnsIndex.size() > 0;
return result;
}
public long getOpenedMarkerSize()
{
return openedMarkerSize;
}
}
}

View File

@ -118,7 +118,7 @@ public class LazilyCompactedRow extends AbstractCompactedRow implements Iterable
DataOutputBuffer clockOut = new DataOutputBuffer();
DeletionTime.serializer.serialize(emptyColumnFamily.deletionInfo().getTopLevelDeletion(), clockOut);
long dataSize = clockOut.getLength() + columnSerializedSize;
long dataSize = clockOut.getLength() + columnSerializedSize + this.indexBuilder.getOpenedMarkerSize();
if (logger.isDebugEnabled())
logger.debug(String.format("clock / column sizes are %s / %s", clockOut.getLength(), columnSerializedSize));
assert dataSize > 0;

View File

@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.junit.Before;
import org.junit.Test;
import org.apache.cassandra.SchemaLoader;
@ -93,8 +94,12 @@ public class LazilyCompactedRowTest extends SchemaLoader
AbstractCompactedRow row2 = iter2.next();
DataOutputBuffer out1 = new DataOutputBuffer();
DataOutputBuffer out2 = new DataOutputBuffer();
row1.write(out1);
row2.write(out2);
long size1 = row1.write(out1);
long size2 = row2.write(out2);
// check if written size is the same as reported row size
assert size1 == out1.getLength() - 8;
assert size2 == out2.getLength() - 8;
File tmpFile1 = File.createTempFile("lcrt1", null);
File tmpFile2 = File.createTempFile("lcrt2", null);
@ -127,9 +132,9 @@ public class LazilyCompactedRowTest extends SchemaLoader
assert columns == in2.readInt();
for (int i = 0; i < columns; i++)
{
IColumn c1 = (IColumn)cf1.getOnDiskSerializer().deserializeFromSSTable(in1, Descriptor.Version.CURRENT);
IColumn c2 = (IColumn)cf2.getOnDiskSerializer().deserializeFromSSTable(in2, Descriptor.Version.CURRENT);
assert c1.equals(c2) : c1.getString(cfs.metadata.comparator) + " != " + c2.getString(cfs.metadata.comparator);
OnDiskAtom c1 = cf1.getOnDiskSerializer().deserializeFromSSTable(in1, Descriptor.Version.CURRENT);
OnDiskAtom c2 = cf2.getOnDiskSerializer().deserializeFromSSTable(in2, Descriptor.Version.CURRENT);
assert c1.equals(c2) : "column mismatch";
}
// that should be everything
assert in1.available() == 0;
@ -166,6 +171,14 @@ public class LazilyCompactedRowTest extends SchemaLoader
}
}
@Before
public void setUp()
{
Table table = Table.open("Keyspace1");
ColumnFamilyStore cfs = table.getColumnFamilyStore("Standard1");
cfs.clearUnsafe();
}
@Test
public void testOneRow() throws IOException, ExecutionException, InterruptedException, NoSuchAlgorithmException
{
@ -314,6 +327,31 @@ public class LazilyCompactedRowTest extends SchemaLoader
assertBytes(cfs, Integer.MAX_VALUE);
}
@Test
public void testOneRowWithRangeTombstone() throws Exception
{
CompactionManager.instance.disableAutoCompaction();
Table table = Table.open("Keyspace1");
ColumnFamilyStore cfs = table.getColumnFamilyStore("Standard1");
ByteBuffer key = ByteBufferUtil.bytes("k");
RowMutation rm = new RowMutation("Keyspace1", key);
ColumnFamily cf = rm.addOrGet(cfs.metadata);
cf.addColumn(new QueryPath("Standard1", null, ByteBufferUtil.bytes("a")), ByteBuffer.allocate(DatabaseDescriptor.getColumnIndexSize()), 1);
cf.addColumn(new QueryPath("Standard1", null, ByteBufferUtil.bytes("c")), ByteBuffer.allocate(DatabaseDescriptor.getColumnIndexSize()), 1);
cf.addColumn(new QueryPath("Standard1", null, ByteBufferUtil.bytes("d")), ByteBuffer.allocate(DatabaseDescriptor.getColumnIndexSize()), 1);
rm.apply();
cfs.forceBlockingFlush();
rm = new RowMutation("Keyspace1", key);
cf = rm.addOrGet(cfs.metadata);
cf.addAtom(new RangeTombstone(ByteBufferUtil.bytes("b"), ByteBufferUtil.bytes("d"), 0, (int)(System.currentTimeMillis()/1000)));
rm.apply();
cfs.forceBlockingFlush();
assertBytes(cfs, 0);
}
private static class LazilyCompactingController extends CompactionController
{
@ -322,6 +360,12 @@ public class LazilyCompactedRowTest extends SchemaLoader
super(cfs, sstables, gcBefore);
}
@Override
public boolean shouldPurge(DecoratedKey key, long maxDeletionTimestamp)
{
return false;
}
@Override
public AbstractCompactedRow getCompactedRow(List<SSTableIdentityIterator> rows)
{
@ -336,6 +380,12 @@ public class LazilyCompactedRowTest extends SchemaLoader
super(cfs, sstables, gcBefore);
}
@Override
public boolean shouldPurge(DecoratedKey key, long maxDeletionTimestamp)
{
return false;
}
@Override
public AbstractCompactedRow getCompactedRow(List<SSTableIdentityIterator> rows)
{