[ https://issues.apache.org/jira/browse/CASSANDRA-17103?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17573987#comment-17573987 ]
David Capwell edited comment on CASSANDRA-17103 at 8/2/22 1:44 AM: ------------------------------------------------------------------- I think accord.topology.TopologyManager#forKeys(accord.txn.Keys, long) also produces the wrong results under some conditions; setup: * RF=1 (this is 100% just to trick accord to touch multiple ranges/shards) * use org.apache.cassandra.dht.Murmur3Partitioner.LongToken#keyForToken to generate a key that maps perfectly to the token for each instance * touch each key In the test above, we should have a min of 2 splits (possible 3rd to account for wrapped ranges), but it actually only has 1! I see that the call to accord.topology.Topology#forKeys(accord.txn.Keys) returns a single shard even though there are 2 keys that map to 2 different shards! The transaction doesn't fail I think because we don't block read/write to out-of-bound ranges Test {code} @Test public void multipleShards() throws Throwable { String keyspace = "ks" + System.currentTimeMillis(); try (Cluster cluster = init(Cluster.build(2).start())) { cluster.schemaChange("CREATE KEYSPACE " + keyspace + " WITH REPLICATION={'class':'SimpleStrategy', 'replication_factor': 1}"); cluster.schemaChange("CREATE TABLE " + keyspace + ".tbl (k blob, c int, v int, primary key (k, c))"); cluster.forEach(node -> node.runOnInstance(() -> AccordService.instance.createEpochFromConfigUnsafe())); cluster.forEach(node -> node.runOnInstance(() -> AccordService.instance.setCacheSize(0))); List<String> tokens = cluster.stream() .flatMap(i -> StreamSupport.stream(Splitter.on(",").split(i.config().getString("initial_token")).spliterator(), false)) .collect(Collectors.toList()); List<byte[]> keys = tokens.stream().map(t -> (Murmur3Partitioner.LongToken) Murmur3Partitioner.instance.getTokenFactory().fromString(t)) .map(Murmur3Partitioner.LongToken::keyForToken) .map(ByteBufferUtil::getArray) .collect(Collectors.toList()); cluster.get(1).runOnInstance(() -> { AccordTxnBuilder txn = txn(); for (byte[] data : keys) { ByteBuffer key = ByteBuffer.wrap(data); txn = txn.withRead("SELECT * FROM " + keyspace + ".tbl WHERE k=? and c=0", key) .withWrite("INSERT INTO " + keyspace + ".tbl (k, c, v) VALUES (?, 0, 0)", key) .withCondition(keyspace, "tbl", key, 0, NOT_EXISTS); } execute(txn); }); } } {code} I wrote this test to hit a condition in accord.coordinate.tracking.ReadTracker#computeMinimalReadSetAndMarkInflight that I thought was odd. {code} this.forEachTrackerForNode(node, (tracker, ignore) -> { toRead.remove(tracker); }); {code} If we do for-each tracker then won't this clear toRead? I wanted to run through a debugger to confirm but got hit by the fact that the Topology only had a single Shard was (Author: dcapwell): I think accord.topology.TopologyManager#forKeys(accord.txn.Keys, long) also produces the wrong results under some conditions; setup: * RF=1 (this is 100% just to trick accord to touch multiple ranges) * use org.apache.cassandra.dht.Murmur3Partitioner.LongToken#keyForToken to generate a key that maps perfectly to the token for each instance * touch each key In the test above, we should have a min of 2 splits (possible 3rd to account for wrapped ranges), but it actually only has 1! I see that the call to accord.topology.Topology#forKeys(accord.txn.Keys) returns a single shard even though there are 2 keys that map to 2 different shards! The transaction doesn't fail I think because we don't block read/write to out-of-bound ranges Test {code} @Test public void multipleShards() throws Throwable { String keyspace = "ks" + System.currentTimeMillis(); try (Cluster cluster = init(Cluster.build(2).start())) { cluster.schemaChange("CREATE KEYSPACE " + keyspace + " WITH REPLICATION={'class':'SimpleStrategy', 'replication_factor': 1}"); cluster.schemaChange("CREATE TABLE " + keyspace + ".tbl (k blob, c int, v int, primary key (k, c))"); cluster.forEach(node -> node.runOnInstance(() -> AccordService.instance.createEpochFromConfigUnsafe())); cluster.forEach(node -> node.runOnInstance(() -> AccordService.instance.setCacheSize(0))); List<String> tokens = cluster.stream() .flatMap(i -> StreamSupport.stream(Splitter.on(",").split(i.config().getString("initial_token")).spliterator(), false)) .collect(Collectors.toList()); List<byte[]> keys = tokens.stream().map(t -> (Murmur3Partitioner.LongToken) Murmur3Partitioner.instance.getTokenFactory().fromString(t)) .map(Murmur3Partitioner.LongToken::keyForToken) .map(ByteBufferUtil::getArray) .collect(Collectors.toList()); cluster.get(1).runOnInstance(() -> { AccordTxnBuilder txn = txn(); for (byte[] data : keys) { ByteBuffer key = ByteBuffer.wrap(data); txn = txn.withRead("SELECT * FROM " + keyspace + ".tbl WHERE k=? and c=0", key) .withWrite("INSERT INTO " + keyspace + ".tbl (k, c, v) VALUES (?, 0, 0)", key) .withCondition(keyspace, "tbl", key, 0, NOT_EXISTS); } execute(txn); }); } } {code} I wrote this test to hit a condition in accord.coordinate.tracking.ReadTracker#computeMinimalReadSetAndMarkInflight that I thought was odd. {code} this.forEachTrackerForNode(node, (tracker, ignore) -> { toRead.remove(tracker); }); {code} If we do for-each tracker then won't this clear toRead? I wanted to run through a debugger to confirm but got hit by the fact that the Topology only had a single Shard > CEP-15 (C*): Messaging and storage engine integration > ----------------------------------------------------- > > Key: CASSANDRA-17103 > URL: https://issues.apache.org/jira/browse/CASSANDRA-17103 > Project: Cassandra > Issue Type: New Feature > Components: Accord > Reporter: Benedict Elliott Smith > Priority: Normal > > This work encompasses implementing Accord’s storage and networking interfaces > within Cassandra, so that messages may be sent around the cluster and > exectuted -- This message was sent by Atlassian Jira (v8.20.10#820010) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org