maedhroz commented on code in PR #4905:
URL: https://github.com/apache/cassandra/pull/4905#discussion_r3501394194


##########
test/unit/org/apache/cassandra/index/sai/memory/VectorMemoryIndexTest.java:
##########
@@ -182,18 +198,489 @@ public void randomQueryTest() throws Exception
                 expectedVectorsReturned += expectedResults;
                 if (foundKeys.size() < expectedResults)
                     assertTrue("Expected at least " + expectedResults + " 
results but got " + foundKeys.size(),
-                               foundKeys.size() >= expectedResults * 
expectedRecall);
+                               foundKeys.size() >= expectedResults * 
RECALL_THRESHOLD);
             }
         }
 
         assertTrue("Expected at least " + expectedVectorsReturned + " results 
but got " + actualVectorsReturned,
-                   actualVectorsReturned >= expectedVectorsReturned * 
expectedRecall);
+                   actualVectorsReturned >= expectedVectorsReturned * 
RECALL_THRESHOLD);
+    }
+
+    /**
+     * Verifies that concurrent calls to add() do not corrupt the graph or 
lose data.
+     * <p>
+     * GraphIndexBuilder.addGraphNode() is designed for concurrent use: 
insertionsInProgress
+     * is a ConcurrentSkipListSet, and PoolingSupport gives each thread its 
own GraphSearcher
+     * and scratch arrays. This test validates the full stack from 
VectorMemoryIndex.index()
+     * through OnHeapGraph.add() through GraphIndexBuilder.addGraphNode().
+     * <p>
+     * Each thread owns a disjoint range of partition key integers so every 
insert is a
+     * pure add with no PK collisions, isolating add() from update() semantics.
+     * <p>
+     * After all writers complete, a full-ring search must return the vast 
majority of
+     * inserted keys with valid scores, confirming no data was lost or 
corrupted.
+     */
+    @Test
+    public void testConcurrentAddsProduceConsistentFinalState() throws 
Exception
+    {
+        Memtable memtable = Mockito.mock(Memtable.class);
+        memtableIndex = new VectorMemoryIndex(index, memtable);
+
+        int numThreads = Runtime.getRuntime().availableProcessors();
+        int vectorsPerThread = 2000;
+        int totalInserted = numThreads * vectorsPerThread;
+
+        ExecutorService executor = Executors.newFixedThreadPool(numThreads);
+        // CyclicBarrier ensures all threads begin inserting simultaneously,
+        // maximizing contention on GraphIndexBuilder and 
ConcurrentVectorValues.
+        CyclicBarrier barrier = new CyclicBarrier(numThreads);
+        List<Future<?>> futures = new ArrayList<>();
+
+        for (int t = 0; t < numThreads; t++)
+        {
+            final int threadId = t;
+            futures.add(executor.submit(() -> {
+                try
+                {
+                    barrier.await();
+                    for (int i = 0; i < vectorsPerThread; i++)
+                    {
+                        // Partition key is globally unique across all threads
+                        int pk = threadId * vectorsPerThread + i;
+                        addRow(pk, randomVectorFromThreadLocal());

Review Comment:
   I think having the threads share a vector sequence would make a lot of 
sense...let's try it...



##########
src/java/org/apache/cassandra/index/sai/memory/VectorMemoryIndex.java:
##########
@@ -98,11 +97,11 @@ public synchronized long add(DecoratedKey key, 
Clustering<?> clustering, ByteBuf
 
     private long index(PrimaryKey primaryKey, ByteBuffer value)
     {
-        updateKeyBounds(primaryKey);
-
         writeCount.increment();
         primaryKeys.add(primaryKey);
-        return graph.add(value, primaryKey, 
OnHeapGraph.InvalidVectorBehavior.FAIL);
+        long bytesUsed = graph.add(value, primaryKey, 
OnHeapGraph.InvalidVectorBehavior.FAIL);

Review Comment:
   Agree



-- 
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