use of org.apache.cassandra.distributed.impl.UnsafeGossipHelper in project cassandra by apache.
the class CASTest method testSuccessfulWriteDuringRangeMovementFollowedByConflicting.
/**
* Successful write during range movement not witnessed by write after range movement
*
* - Range moves from {1, 2, 3} to {2, 3, 4}; witnessed by X (not by !X)
* - !X: Prepare and Propose to {1, 2}
* - Range movement witnessed by !X
* - Any: Prepare and Propose to {3, 4}
*/
@Ignore
@Test
public void testSuccessfulWriteDuringRangeMovementFollowedByConflicting() throws Throwable {
try (Cluster cluster = Cluster.create(4, config -> config.set("write_request_timeout", REQUEST_TIMEOUT).set("cas_contention_timeout", CONTENTION_TIMEOUT))) {
cluster.schemaChange("CREATE KEYSPACE " + KEYSPACE + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3};");
cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, ck int, v1 int, v2 int, PRIMARY KEY (pk, ck))");
// make it so {4} is bootstrapping, and this has not propagated to other nodes yet
for (int i = 1; i <= 4; ++i) cluster.get(1).acceptsOnInstance(UnsafeGossipHelper::removeFromRing).accept(cluster.get(4));
cluster.get(4).acceptsOnInstance(UnsafeGossipHelper::addToRingBootstrapping).accept(cluster.get(4));
int pk = pk(cluster, 1, 2);
// {1} promises and accepts on !{3} => {1, 2}; commits on !{2, 3} => {1}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_COMMIT_REQ.id).from(1).to(2, 3).drop();
assertRows(cluster.coordinator(1).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v1) VALUES (?, 1, 1) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(true));
// finish topology change
for (int i = 1; i <= 4; ++i) cluster.get(i).acceptsOnInstance(UnsafeGossipHelper::addToRingNormal).accept(cluster.get(4));
// {3} reads from !{2} => {3, 4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(3).to(2).drop();
assertRows(cluster.coordinator(3).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v2) VALUES (?, 1, 2) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(false, pk, 1, 1, null));
// TODO: repair and verify base table state
}
}
use of org.apache.cassandra.distributed.impl.UnsafeGossipHelper in project cassandra by apache.
the class CASTest method testIncompleteWriteFollowedBySuccessfulWriteWithStaleRingDuringRangeMovementFollowedByWrite.
/**
* During a range movement, a CAS may fail leaving side effects that are not witnessed by another operation
* being performed with stale ring information.
* This is a particular special case of stale ring information sequencing, which probably would be resolved
* by fixing each of the more isolated cases (but is unique, so deserving of its own test case).
* See CASSANDRA-15745
*
* - Range moves from {1, 2, 3} to {2, 3, 4}; witnessed by X (not by !X)
* - X: Prepare to {2, 3, 4}
* - X: Propose to {4}
* - !X: Prepare and Propose to {1, 2}
* - Range move visible by !X
* - Any: Prepare and Propose to {3, 4}
*/
@Ignore
@Test
public void testIncompleteWriteFollowedBySuccessfulWriteWithStaleRingDuringRangeMovementFollowedByWrite() throws Throwable {
try (Cluster cluster = Cluster.create(4, config -> config.set("write_request_timeout", REQUEST_TIMEOUT).set("cas_contention_timeout", CONTENTION_TIMEOUT))) {
cluster.schemaChange("CREATE KEYSPACE " + KEYSPACE + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3};");
cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, ck int, v1 int, v2 int, PRIMARY KEY (pk, ck))");
// make it so {4} is bootstrapping, and this has not propagated to other nodes yet
for (int i = 1; i <= 4; ++i) cluster.get(1).acceptsOnInstance(UnsafeGossipHelper::removeFromRing).accept(cluster.get(4));
cluster.get(4).acceptsOnInstance(UnsafeGossipHelper::addToRingBootstrapping).accept(cluster.get(4));
int pk = pk(cluster, 1, 2);
// {4} promises and accepts on !{1} => {2, 3, 4}; commits on !{1, 2, 3} => {4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(4).to(1).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(4).to(1, 2, 3).drop();
try {
cluster.coordinator(4).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v1) VALUES (?, 1, 1) IF NOT EXISTS", ConsistencyLevel.QUORUM, pk);
Assert.assertTrue(false);
} catch (RuntimeException wrapped) {
Assert.assertEquals("Operation timed out - received only 1 responses.", wrapped.getCause().getMessage());
}
// {1} promises and accepts on !{3} => {1, 2}; commits on !{2, 3} => {1}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_COMMIT_REQ.id).from(1).to(2, 3).drop();
assertRows(cluster.coordinator(1).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v2) VALUES (?, 1, 2) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(true));
// finish topology change
for (int i = 1; i <= 4; ++i) cluster.get(i).acceptsOnInstance(UnsafeGossipHelper::addToRingNormal).accept(cluster.get(4));
// {3} reads from !{2} => {3, 4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(3).to(2).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(3).to(2).drop();
assertRows(cluster.coordinator(3).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v2) VALUES (?, 1, 2) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(false, 5, 1, null, 2));
}
}
use of org.apache.cassandra.distributed.impl.UnsafeGossipHelper in project cassandra by apache.
the class CASTest method testSucccessfulWriteDuringRangeMovementFollowedByRead.
/**
* Successful write during range movement, not witnessed by read after range movement.
* Very similar to {@link #testConflictingWritesWithStaleRingInformation}.
*
* - Range moves from {1, 2, 3} to {2, 3, 4}; witnessed by X (not by !X)
* - !X: Prepare and Propose to {1, 2}
* - Range movement witnessed by !X
* - Any: Prepare and Read from {3, 4}
*/
@Ignore
@Test
public void testSucccessfulWriteDuringRangeMovementFollowedByRead() throws Throwable {
try (Cluster cluster = Cluster.create(4, config -> config.set("write_request_timeout", REQUEST_TIMEOUT).set("cas_contention_timeout", CONTENTION_TIMEOUT))) {
cluster.schemaChange("CREATE KEYSPACE " + KEYSPACE + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3};");
cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, ck int, v int, PRIMARY KEY (pk, ck))");
// make it so {4} is bootstrapping, and this has not propagated to other nodes yet
for (int i = 1; i <= 4; ++i) cluster.get(1).acceptsOnInstance(UnsafeGossipHelper::removeFromRing).accept(cluster.get(4));
cluster.get(4).acceptsOnInstance(UnsafeGossipHelper::addToRingBootstrapping).accept(cluster.get(4));
int pk = pk(cluster, 1, 2);
// {1} promises and accepts on !{3} => {1, 2}; commmits on !{2, 3} => {1}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_COMMIT_REQ.id).from(1).to(2, 3).drop();
assertRows(cluster.coordinator(1).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v) VALUES (?, 1, 1) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(true));
// finish topology change
for (int i = 1; i <= 4; ++i) cluster.get(i).acceptsOnInstance(UnsafeGossipHelper::addToRingNormal).accept(cluster.get(4));
// {3} reads from !{2} => {3, 4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(3).to(2).drop();
assertRows(cluster.coordinator(3).execute("SELECT * FROM " + KEYSPACE + ".tbl WHERE pk = ?", ConsistencyLevel.SERIAL, pk), row(pk, 1, 1));
}
}
use of org.apache.cassandra.distributed.impl.UnsafeGossipHelper in project cassandra by apache.
the class CASTest method testSuccessfulWriteBeforeRangeMovement.
/**
* Failed write (by node that did not yet witness a range movement via gossip) is witnessed later as successful
* conflicting with another successful write performed by a node that did witness the range movement
* Prepare, Propose and Commit A to {1, 2}
* Range moves to {2, 3, 4}
* Prepare and Propose B (=> !A) to {3, 4}
*/
@Ignore
@Test
public void testSuccessfulWriteBeforeRangeMovement() throws Throwable {
try (Cluster cluster = Cluster.create(4, config -> config.set("write_request_timeout", REQUEST_TIMEOUT).set("cas_contention_timeout", CONTENTION_TIMEOUT))) {
cluster.schemaChange("CREATE KEYSPACE " + KEYSPACE + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3};");
cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, ck int, v1 int, v2 int, PRIMARY KEY (pk, ck))");
// make it so {1} is unaware (yet) that {4} is an owner of the token
cluster.get(1).acceptsOnInstance(UnsafeGossipHelper::removeFromRing).accept(cluster.get(4));
int pk = pk(cluster, 1, 2);
// {1} promises and accepts on !{3} => {1, 2}; commits on !{2,3} => {1}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_COMMIT_REQ.id).from(1).to(2, 3).drop();
assertRows(cluster.coordinator(1).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v1) VALUES (?, 1, 1) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(true));
for (int i = 1; i <= 3; ++i) cluster.get(i).acceptsOnInstance(UnsafeGossipHelper::addToRingNormal).accept(cluster.get(4));
// {4} reads from !{2} => {3, 4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(4).to(2).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(4).to(2).drop();
assertRows(cluster.coordinator(4).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v2) VALUES (?, 1, 2) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(false, pk, 1, 1, null));
}
}
use of org.apache.cassandra.distributed.impl.UnsafeGossipHelper in project cassandra by apache.
the class CASTest method testIncompleteWriteFollowedBySuccessfulWriteWithStaleRingDuringRangeMovementFollowedByRead.
/**
* During a range movement, a CAS may fail leaving side effects that are not witnessed by another operation
* being performed with stale ring information.
* This is a particular special case of stale ring information sequencing, which probably would be resolved
* by fixing each of the more isolated cases (but is unique, so deserving of its own test case).
* See CASSANDRA-15745
*
* - Range moves from {1, 2, 3} to {2, 3, 4}; witnessed by X (not by !X)
* - X: Prepare to {2, 3, 4}
* - X: Propose to {4}
* - !X: Prepare and Propose to {1, 2}
* - Range move visible by !X
* - Any: Prepare and Read from {3, 4}
*/
@Ignore
@Test
public void testIncompleteWriteFollowedBySuccessfulWriteWithStaleRingDuringRangeMovementFollowedByRead() throws Throwable {
try (Cluster cluster = Cluster.create(4, config -> config.set("write_request_timeout", REQUEST_TIMEOUT).set("cas_contention_timeout", CONTENTION_TIMEOUT))) {
cluster.schemaChange("CREATE KEYSPACE " + KEYSPACE + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 3};");
cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, ck int, v1 int, v2 int, PRIMARY KEY (pk, ck))");
// make it so {4} is bootstrapping, and this has not propagated to other nodes yet
for (int i = 1; i <= 4; ++i) cluster.get(1).acceptsOnInstance(UnsafeGossipHelper::removeFromRing).accept(cluster.get(4));
cluster.get(4).acceptsOnInstance(UnsafeGossipHelper::addToRingBootstrapping).accept(cluster.get(4));
int pk = pk(cluster, 1, 2);
// {4} promises and accepts on !{1} => {2, 3, 4}; commits on !{1, 2, 3} => {4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(4).to(1).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(4).to(1, 2, 3).drop();
try {
cluster.coordinator(4).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v1) VALUES (?, 1, 1) IF NOT EXISTS", ConsistencyLevel.QUORUM, pk);
Assert.assertTrue(false);
} catch (RuntimeException wrapped) {
Assert.assertEquals("Operation timed out - received only 1 responses.", wrapped.getCause().getMessage());
}
// {1} promises and accepts on !{3} => {1, 2}; commits on !{2, 3} => {1}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(1).to(3).drop();
cluster.filters().verbs(PAXOS_COMMIT_REQ.id).from(1).to(2, 3).drop();
assertRows(cluster.coordinator(1).execute("INSERT INTO " + KEYSPACE + ".tbl (pk, ck, v2) VALUES (?, 1, 2) IF NOT EXISTS", ConsistencyLevel.ONE, pk), row(true));
// finish topology change
for (int i = 1; i <= 4; ++i) cluster.get(i).acceptsOnInstance(UnsafeGossipHelper::addToRingNormal).accept(cluster.get(4));
// {3} reads from !{2} => {3, 4}
cluster.filters().verbs(PAXOS_PREPARE_REQ.id, READ_REQ.id).from(3).to(2).drop();
cluster.filters().verbs(PAXOS_PROPOSE_REQ.id).from(3).to(2).drop();
assertRows(cluster.coordinator(3).execute("SELECT * FROM " + KEYSPACE + ".tbl WHERE pk = ?", ConsistencyLevel.SERIAL, pk), row(pk, 1, null, 2));
}
}
Aggregations