This is an automated email from the ASF dual-hosted git repository.

jchovatia pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new a06df099f4 No need to evict already prepared statements, as it creates 
a race condition between multiple threads
a06df099f4 is described below

commit a06df099f4e1c6265d25c94336c493aded3aa644
Author: Jaydeepkumar Chovatia <[email protected]>
AuthorDate: Sun Jan 21 12:44:56 2024 -0800

    No need to evict already prepared statements, as it creates a race 
condition between multiple threads
    
    patch by Jaydeepkumar Chovatia; reviewed by Alex Petrov for CASSANDRA-17401
---
 CHANGES.txt                                        |  1 +
 .../org/apache/cassandra/cql3/QueryProcessor.java  |  7 --
 .../miscellaneous/PreparedStatementTest.java       | 85 ++++++++++++++++++++++
 3 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index c748e17c1f..e78d5bfd6e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 5.1
+ * No need to evict already prepared statements, as it creates a race 
condition between multiple threads (CASSANDRA-17401)
  * Include Level information for UnifiedCompactionStrategy in nodetool 
tablestats output (CASSANDRA-20820)
  * Support low-overhead async profiling (CASSANDRA-20854)
  * Minor perf optimizations around memtable put logic (CASSANDRA-21088)
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java 
b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index 38a0f3545b..606da47305 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -803,13 +803,6 @@ public class QueryProcessor implements QueryHandler
                 return createResultMessage(hashWithKeyspace, 
cachedWithKeyspace);
             }
         }
-        else
-        {
-            // Make sure the missing one is going to be eventually re-prepared
-            evictPrepared(hashWithKeyspace);
-            evictPrepared(hashWithoutKeyspace);
-        }
-
         Prepared prepared = parseAndPrepare(queryString, clientState, false);
         CQLStatement statement = prepared.statement;
 
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/PreparedStatementTest.java
 
b/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/PreparedStatementTest.java
new file mode 100644
index 0000000000..a0bebed43c
--- /dev/null
+++ 
b/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/PreparedStatementTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.cql3.validation.miscellaneous;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.QueryProcessor;
+import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.transport.messages.ResultMessage;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class PreparedStatementTest extends CQLTester
+{
+    private static final int NUM_THREADS = 50;
+    private final CountDownLatch startLatch = new CountDownLatch(1);
+    private final CountDownLatch finishLatch = new CountDownLatch(NUM_THREADS);
+
+    @Test
+    public void testPreparedStatementStaysInCache() throws Throwable
+    {
+        execute("CREATE TABLE " + KEYSPACE + ".test_fullyqualified(a int 
primary key, b int)");
+
+        ClientState state = ClientState.forInternalCalls();
+        Assert.assertEquals(0, 
QueryProcessor.instance.getPreparedStatements().size());
+        final ResultMessage.Prepared[] preparedSelect = new 
ResultMessage.Prepared[NUM_THREADS];
+        AtomicBoolean preparedStatementPresentInCache = new 
AtomicBoolean(true);
+        for (int i = 0; i < NUM_THREADS; i++)
+        {
+            int threadId = i;
+            Thread thread = new Thread(() -> {
+                try
+                {
+                    // Wait until the start signal is given
+                    startLatch.await();
+
+                    // Code to be executed in each thread
+                    preparedSelect[threadId] = QueryProcessor.instance.prepare(
+                    String.format("SELECT b FROM %s.test_fullyqualified where 
a = 10", KEYSPACE), state);
+                    Assert.assertNotNull(preparedSelect[threadId].statementId);
+                    
if(!QueryProcessor.instance.getPreparedStatements().containsKey(preparedSelect[threadId].statementId))
+                    {
+                        preparedStatementPresentInCache.set(false);
+                    }
+                }
+                catch (InterruptedException e)
+                {
+                    Thread.currentThread().interrupt();
+                }
+                finally
+                {
+                    // Signal that this thread has finished
+                    finishLatch.countDown();
+                }
+                Assert.fail();
+            });
+            thread.start();
+        }
+
+        // Signal all threads to start
+        startLatch.countDown();
+
+        // Wait for all threads to finish
+        finishLatch.await();
+        Assert.assertTrue(preparedStatementPresentInCache.get());
+    }
+}


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

Reply via email to