dcapwell commented on code in PR #3157:
URL: https://github.com/apache/cassandra/pull/3157#discussion_r1511826671


##########
test/unit/org/apache/cassandra/service/accord/AccordKeyspaceTest.java:
##########
@@ -97,4 +134,157 @@ public void serde()
         Command loaded = AccordKeyspace.loadCommand(store, id);
         Assertions.assertThat(loaded).isEqualTo(committed);
     }
+
+    @Test
+    public void findOverlappingKeys()
+    {
+        var tableIdGen = fromQT(CassandraGenerators.TABLE_ID_GEN);
+        var partitionGen = fromQT(CassandraGenerators.partitioners());
+
+        var sstableFormats = DatabaseDescriptor.getSSTableFormats();
+        List<String> sstableFormatNames = new 
ArrayList<>(sstableFormats.keySet());
+        sstableFormatNames.sort(Comparator.naturalOrder());
+
+        List<String> memtableFormats = 
MemtableParams.knownDefinitions().stream()
+                                                     .filter(name -> 
!name.startsWith("test_") && !name.equals("default"))
+                                                     .sorted()
+                                                     
.collect(Collectors.toList());
+
+        qt().check(rs -> {
+            AccordKeyspace.unsafeClear();
+            // control SSTable format
+            
setSelectedSSTableFormat(sstableFormats.get(rs.pick(sstableFormatNames)));
+            // control memtable format
+            setMemtable(ACCORD_KEYSPACE_NAME, "commands_for_key", 
rs.pick(memtableFormats));
+
+            // define the tables w/ partitioners for the test
+            // this uses the ability to override the SchemaProvider for the 
keyspace and only defines the single API call expected: getTablePartitioner
+            TreeMap<TableId, IPartitioner> tables = new TreeMap<>();
+            int numTables = rs.nextInt(1, 3);
+            for (int i = 0; i < numTables; i++)
+            {
+                var tableId = tableIdGen.next(rs);
+                while (tables.containsKey(tableId))
+                    tableId = tableIdGen.next(rs);
+                tables.put(tableId, partitionGen.next(rs));
+            }
+            SchemaProvider schema = Mockito.mock(SchemaProvider.class);
+            
Mockito.when(schema.getTablePartitioner(Mockito.any())).thenAnswer((Answer<IPartitioner>)
 invocationOnMock -> tables.get(invocationOnMock.getArgument(0)));
+            AccordKeyspace.unsafeSetSchema(schema);
+
+            int numStores = rs.nextInt(1, 3);
+
+            // The model of the DB
+            TreeMap<Integer, SortedSet<PartitionKey>> storesToKeys = new 
TreeMap<>();
+            // write to the table and the model
+            for (int i = 0, numKeys = rs.nextInt(10, 20); i < numKeys; i++)
+            {
+                int store = rs.nextInt(0, numStores);
+                var keys = storesToKeys.computeIfAbsent(store, ignore -> new 
TreeSet<>());
+                PartitionKey pk = null;
+                // LocalPartitioner may have a type with a very small domain 
(boolean, vector<boolean, 1>, etc.), so need to bound the attempts
+                // else this will loop forever...
+                for (int attempt = 0; attempt < 10; attempt++)
+                {
+                    TableId tableId = rs.pick(tables.keySet());
+                    IPartitioner partitioner = tables.get(tableId);
+                    ByteBuffer data = !(partitioner instanceof 
LocalPartitioner) ? Int32Type.instance.decompose(rs.nextInt())
+                                                                               
  : fromQT(getTypeSupport(partitioner.getTokenValidator()).bytesGen()).next(rs);
+                    PartitionKey key = new PartitionKey(tableId, 
tables.get(tableId).decorateKey(data));
+                    if (keys.add(key))
+                    {
+                        pk = key;
+                        break;
+                    }
+                }
+                if (pk != null)
+                {
+                    try
+                    {
+                        // using Mutation directly (what we do in Accord) can 
break when user data is too large; leading to data loss
+                        // The memtable will allow the write, but it will be 
dropped when writing to the SSTable...
+                        //TODO (now, correctness): since we store the user 
token + user key, if a key is close to the PK limits then we could tip over and 
loose our CFK
+//                        new 
Mutation(AccordKeyspace.getCommandsForKeyPartitionUpdate(store, pk, 42, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)).apply();

Review Comment:
   this is the logic CFK uses, but this can cause problems down the road.  For 
this test these keys are filtered out and CQL is used directly to avoid these 
issues...
   
   There is a task to fix CFK to not have size limits that different than 
normal CQL



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to