use of org.apache.cassandra.locator.EndpointsForRange in project cassandra by apache.
the class DataResolverTest method resolveRangeTombstonesOnBoundary.
/*
* We want responses to merge on tombstone boundary. So we'll merge 2 "streams":
* 1: [1, 2)(3, 4](5, 6] 2
* 2: [2, 3][4, 5) 1
* which tests all combination of open/close boundaries (open/close, close/open, open/open, close/close).
*
* Note that, because DataResolver returns a "filtered" iterator, it should resolve into an empty iterator.
* However, what should be sent to each source depends on the exact on the timestamps of each tombstones and we
* test a few combination.
*/
private void resolveRangeTombstonesOnBoundary(long timestamp1, long timestamp2) {
EndpointsForRange replicas = makeReplicas(2);
DataResolver resolver = new DataResolver(command, plan(replicas, ALL), readRepair, nanoTime());
InetAddressAndPort peer1 = replicas.get(0).endpoint();
InetAddressAndPort peer2 = replicas.get(1).endpoint();
// 1st "stream"
RangeTombstone one_two = tombstone("1", true, "2", false, timestamp1, nowInSec);
RangeTombstone three_four = tombstone("3", false, "4", true, timestamp1, nowInSec);
RangeTombstone five_six = tombstone("5", false, "6", true, timestamp1, nowInSec);
UnfilteredPartitionIterator iter1 = iter(new RowUpdateBuilder(cfm, nowInSec, 1L, dk).addRangeTombstone(one_two).addRangeTombstone(three_four).addRangeTombstone(five_six).buildUpdate());
// 2nd "stream"
RangeTombstone two_three = tombstone("2", true, "3", true, timestamp2, nowInSec);
RangeTombstone four_five = tombstone("4", true, "5", false, timestamp2, nowInSec);
UnfilteredPartitionIterator iter2 = iter(new RowUpdateBuilder(cfm, nowInSec, 1L, dk).addRangeTombstone(two_three).addRangeTombstone(four_five).buildUpdate());
resolver.preprocess(response(command, peer1, iter1));
resolver.preprocess(response(command, peer2, iter2));
// No results, we've only reconciled tombstones.
try (PartitionIterator data = resolver.resolve()) {
assertFalse(data.hasNext());
}
assertEquals(2, readRepair.sent.size());
Mutation msg1 = readRepair.getForEndpoint(peer1);
assertRepairMetadata(msg1);
assertRepairContainsNoColumns(msg1);
Mutation msg2 = readRepair.getForEndpoint(peer2);
assertRepairMetadata(msg2);
assertRepairContainsNoColumns(msg2);
// Both streams are mostly complementary, so they will roughly get the ranges of the other stream. One subtlety is
// around the value "4" however, as it's included by both stream.
// So for a given stream, unless the other stream has a strictly higher timestamp, the value 4 will be excluded
// from whatever range it receives as repair since the stream already covers it.
// Message to peer1 contains peer2 ranges
assertRepairContainsDeletions(msg1, null, two_three, withExclusiveStartIf(four_five, timestamp1 >= timestamp2));
// Message to peer2 contains peer1 ranges
assertRepairContainsDeletions(msg2, null, one_two, withExclusiveEndIf(three_four, timestamp2 >= timestamp1), five_six);
}
use of org.apache.cassandra.locator.EndpointsForRange in project cassandra by apache.
the class DataResolverTest method testResolveDeletedCollection.
@Test
public void testResolveDeletedCollection() {
EndpointsForRange replicas = makeReplicas(2);
ReadCommand cmd = Util.cmd(cfs2, dk).withNowInSeconds(nowInSec).build();
TestableReadRepair readRepair = new TestableReadRepair(cmd);
DataResolver resolver = new DataResolver(cmd, plan(replicas, ALL), readRepair, nanoTime());
long[] ts = { 100, 200 };
Row.Builder builder = BTreeRow.unsortedBuilder();
builder.newRow(Clustering.EMPTY);
builder.addComplexDeletion(m, new DeletionTime(ts[0] - 1, nowInSec));
builder.addCell(mapCell(0, 0, ts[0]));
InetAddressAndPort peer1 = replicas.get(0).endpoint();
resolver.preprocess(response(cmd, peer1, iter(PartitionUpdate.singleRowUpdate(cfm2, dk, builder.build()))));
builder.newRow(Clustering.EMPTY);
DeletionTime expectedCmplxDelete = new DeletionTime(ts[1] - 1, nowInSec);
builder.addComplexDeletion(m, expectedCmplxDelete);
InetAddressAndPort peer2 = replicas.get(1).endpoint();
resolver.preprocess(response(cmd, peer2, iter(PartitionUpdate.singleRowUpdate(cfm2, dk, builder.build()))));
try (PartitionIterator data = resolver.resolve()) {
assertFalse(data.hasNext());
}
Mutation mutation = readRepair.getForEndpoint(peer1);
Iterator<Row> rowIter = mutation.getPartitionUpdate(cfm2).iterator();
assertTrue(rowIter.hasNext());
Row row = rowIter.next();
assertFalse(rowIter.hasNext());
ComplexColumnData cd = row.getComplexColumnData(m);
assertEquals(Collections.emptySet(), Sets.newHashSet(cd));
assertEquals(expectedCmplxDelete, cd.complexDeletion());
Assert.assertNull(readRepair.sent.get(peer2));
}
use of org.apache.cassandra.locator.EndpointsForRange in project cassandra by apache.
the class DataResolverTest method testResolveDisjointMultipleRowsWithRangeTombstones.
@Test
public void testResolveDisjointMultipleRowsWithRangeTombstones() {
EndpointsForRange replicas = makeReplicas(4);
DataResolver resolver = new DataResolver(command, plan(replicas, ALL), readRepair, nanoTime());
RangeTombstone tombstone1 = tombstone("1", "11", 1, nowInSec);
RangeTombstone tombstone2 = tombstone("3", "31", 1, nowInSec);
PartitionUpdate update = new RowUpdateBuilder(cfm3, nowInSec, 1L, dk).addRangeTombstone(tombstone1).addRangeTombstone(tombstone2).buildUpdate();
InetAddressAndPort peer1 = replicas.get(0).endpoint();
UnfilteredPartitionIterator iter1 = iter(new RowUpdateBuilder(cfm3, nowInSec, 1L, dk).addRangeTombstone(tombstone1).addRangeTombstone(tombstone2).buildUpdate());
resolver.preprocess(response(command, peer1, iter1));
// not covered by any range tombstone
InetAddressAndPort peer2 = replicas.get(1).endpoint();
UnfilteredPartitionIterator iter2 = iter(new RowUpdateBuilder(cfm3, nowInSec, 0L, dk).clustering("0").add("c1", "v0").buildUpdate());
resolver.preprocess(response(command, peer2, iter2));
// covered by a range tombstone
InetAddressAndPort peer3 = replicas.get(2).endpoint();
UnfilteredPartitionIterator iter3 = iter(new RowUpdateBuilder(cfm3, nowInSec, 0L, dk).clustering("10").add("c2", "v1").buildUpdate());
resolver.preprocess(response(command, peer3, iter3));
// range covered by rt, but newer
InetAddressAndPort peer4 = replicas.get(3).endpoint();
UnfilteredPartitionIterator iter4 = iter(new RowUpdateBuilder(cfm3, nowInSec, 2L, dk).clustering("3").add("one", "A").buildUpdate());
resolver.preprocess(response(command, peer4, iter4));
try (PartitionIterator data = resolver.resolve()) {
try (RowIterator rows = data.next()) {
Row row = rows.next();
assertClustering(cfm, row, "0");
assertColumns(row, "c1");
assertColumn(cfm, row, "c1", "v0", 0);
row = rows.next();
assertClustering(cfm, row, "3");
assertColumns(row, "one");
assertColumn(cfm, row, "one", "A", 2);
assertFalse(rows.hasNext());
}
}
assertEquals(4, readRepair.sent.size());
// peer1 needs the rows from peers 2 and 4
Mutation mutation = readRepair.getForEndpoint(peer1);
assertRepairMetadata(mutation);
assertRepairContainsNoDeletions(mutation);
assertRepairContainsColumn(mutation, "0", "c1", "v0", 0);
assertRepairContainsColumn(mutation, "3", "one", "A", 2);
// peer2 needs to get the row from peer4 and the RTs
mutation = readRepair.getForEndpoint(peer2);
assertRepairMetadata(mutation);
assertRepairContainsDeletions(mutation, null, tombstone1, tombstone2);
assertRepairContainsColumn(mutation, "3", "one", "A", 2);
// peer 3 needs both rows and the RTs
mutation = readRepair.getForEndpoint(peer3);
assertRepairMetadata(mutation);
assertRepairContainsDeletions(mutation, null, tombstone1, tombstone2);
assertRepairContainsColumn(mutation, "0", "c1", "v0", 0);
assertRepairContainsColumn(mutation, "3", "one", "A", 2);
// peer4 needs the row from peer2 and the RTs
mutation = readRepair.getForEndpoint(peer4);
assertRepairMetadata(mutation);
assertRepairContainsDeletions(mutation, null, tombstone1, tombstone2);
assertRepairContainsColumn(mutation, "0", "c1", "v0", 0);
}
use of org.apache.cassandra.locator.EndpointsForRange in project cassandra by apache.
the class DataResolverTest method testResolveMultipleDeleted.
@Test
public void testResolveMultipleDeleted() {
EndpointsForRange replicas = makeReplicas(4);
DataResolver resolver = new DataResolver(command, plan(replicas, ALL), readRepair, nanoTime());
// deletes and columns with interleaved timestamp, with out of order return sequence
InetAddressAndPort peer1 = replicas.get(0).endpoint();
resolver.preprocess(response(command, peer1, fullPartitionDelete(cfm, dk, 0, nowInSec)));
// these columns created after the previous deletion
InetAddressAndPort peer2 = replicas.get(1).endpoint();
resolver.preprocess(response(command, peer2, iter(new RowUpdateBuilder(cfm, nowInSec, 1L, dk).clustering("1").add("one", "A").add("two", "A").buildUpdate())));
// this column created after the next delete
InetAddressAndPort peer3 = replicas.get(2).endpoint();
resolver.preprocess(response(command, peer3, iter(new RowUpdateBuilder(cfm, nowInSec, 3L, dk).clustering("1").add("two", "B").buildUpdate())));
InetAddressAndPort peer4 = replicas.get(3).endpoint();
resolver.preprocess(response(command, peer4, fullPartitionDelete(cfm, dk, 2, nowInSec)));
try (PartitionIterator data = resolver.resolve()) {
try (RowIterator rows = Iterators.getOnlyElement(data)) {
Row row = Iterators.getOnlyElement(rows);
assertColumns(row, "two");
assertColumn(cfm, row, "two", "B", 3);
}
}
// peer 1 needs to get the partition delete from peer 4 and the row from peer 3
assertEquals(4, readRepair.sent.size());
Mutation mutation = readRepair.getForEndpoint(peer1);
assertRepairMetadata(mutation);
assertRepairContainsDeletions(mutation, new DeletionTime(2, nowInSec));
assertRepairContainsColumn(mutation, "1", "two", "B", 3);
// peer 2 needs the deletion from peer 4 and the row from peer 3
mutation = readRepair.getForEndpoint(peer2);
assertRepairMetadata(mutation);
assertRepairContainsDeletions(mutation, new DeletionTime(2, nowInSec));
assertRepairContainsColumn(mutation, "1", "two", "B", 3);
// peer 3 needs just the deletion from peer 4
mutation = readRepair.getForEndpoint(peer3);
assertRepairMetadata(mutation);
assertRepairContainsDeletions(mutation, new DeletionTime(2, nowInSec));
assertRepairContainsNoColumns(mutation);
// peer 4 needs just the row from peer 3
mutation = readRepair.getForEndpoint(peer4);
assertRepairMetadata(mutation);
assertRepairContainsNoDeletions(mutation);
assertRepairContainsColumn(mutation, "1", "two", "B", 3);
}
use of org.apache.cassandra.locator.EndpointsForRange in project cassandra by apache.
the class DataResolverTest method trackMismatchingRepairedDigestsWithNoneConclusive.
@Test
public void trackMismatchingRepairedDigestsWithNoneConclusive() {
ByteBuffer digest1 = ByteBufferUtil.bytes("digest1");
ByteBuffer digest2 = ByteBufferUtil.bytes("digest2");
EndpointsForRange replicas = makeReplicas(2);
InetAddressAndPort peer1 = replicas.get(0).endpoint();
InetAddressAndPort peer2 = replicas.get(1).endpoint();
TestRepairedDataVerifier verifier = new TestRepairedDataVerifier();
verifier.expectDigest(peer1, digest1, false);
verifier.expectDigest(peer2, digest2, false);
DataResolver resolver = resolverWithVerifier(command, plan(replicas, ALL), readRepair, nanoTime(), verifier);
resolver.preprocess(response(peer1, iter(PartitionUpdate.emptyUpdate(cfm, dk)), digest1, false, command));
resolver.preprocess(response(peer2, iter(PartitionUpdate.emptyUpdate(cfm, dk)), digest2, false, command));
resolveAndConsume(resolver);
assertTrue(verifier.verified);
}
Aggregations