diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java
index 05bc45a7900..8e89c6185e6 100644
--- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java
+++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/helper/WriteLockManager.java
@@ -135,6 +135,8 @@ public class WriteLockManager {
private final Lock instancePrevailingQueueLock = new ReentrantLock();
private final Condition toWaitOnLockCondition = toWaitOnLock.newCondition();
+ private static final String ACQUIRE_LOCK_FOR_CLONE_METHOD_NAME = WriteLockManager.class.getName() + ".acquireLocksForClone(...)";
+
public WriteLockManager() {
this.prevailingQueue = new ExposedNodeLinkedList();
}
@@ -170,9 +172,8 @@ public Map acquireLocksForClone(Object objectForClone, ClassDescriptor descripto
// of the concurrency manager that we use for creating the massive log dump
// to indicate that the current thread is now stuck trying to acquire some arbitrary
// cache key for writing
- StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[1];
lastCacheKeyWeNeededToWaitToAcquire = toWaitOn;
- lastCacheKeyWeNeededToWaitToAcquire.putThreadAsWaitingToAcquireLockForWriting(currentThread, stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + "(...)");
+ lastCacheKeyWeNeededToWaitToAcquire.putThreadAsWaitingToAcquireLockForWriting(currentThread, ACQUIRE_LOCK_FOR_CLONE_METHOD_NAME);
// Since we know this one of those methods that can appear in the dead locks
// we threads frozen here forever inside of the wait that used to have no timeout
diff --git a/jpa/eclipselink.jpa.test.jse/pom.xml b/jpa/eclipselink.jpa.test.jse/pom.xml
index bdea2e7e125..d03a34f812e 100644
--- a/jpa/eclipselink.jpa.test.jse/pom.xml
+++ b/jpa/eclipselink.jpa.test.jse/pom.xml
@@ -41,16 +41,6 @@
junit
test
-
- jakarta.enterprise
- jakarta.enterprise.cdi-api
- test
-
-
- org.jboss.weld.se
- weld-se-core
- test
-
@@ -210,32 +200,18 @@
- test-jpa-jse-without-deadlock
+ test-jpa-jse
integration-test
${test-skip-jpa-jse}
test-jpa-jse
-
- CacheDeadLockDetectionTest*
-
*.Test*
-
- test-jpa-jse-deadlock
-
- integration-test
-
-
-
- CacheDeadLockDetectionTest*
-
-
-
verify-integration-tests
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/CacheDeadLockDetectionTest.java b/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/CacheDeadLockDetectionTest.java
deleted file mode 100644
index e4e34fad4c2..00000000000
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/CacheDeadLockDetectionTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
- */
-
-// Contributors:
-// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock;
-
-import jakarta.enterprise.inject.se.SeContainer;
-import jakarta.enterprise.inject.se.SeContainerInitializer;
-
-import jakarta.persistence.*;
-
-import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
-import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionDetail;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster;
-import org.eclipse.persistence.jpa.test.cachedeadlock.cdi.event.EventProducer;
-
-import org.eclipse.persistence.sessions.DatabaseSession;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-public class CacheDeadLockDetectionTest {
-
- public static final int RECORDS_NO = 10;
- public static final int NO_OF_THREADS = 100;
-
- public static EntityManagerFactory emf = Persistence.createEntityManagerFactory("cachedeadlockdetection-pu");
- public static EntityManagerFactory emfSemaphore = Persistence.createEntityManagerFactory("cachedeadlocksemaphore-pu");
-
- SeContainer container;
-
- EventProducer eventProducer;
-
- @Test
- public void bugTest() {
- EntityManager em = emf.createEntityManager();
- verifyPersistenceProperties();
- setup();
- try {
- em.getTransaction().begin();
- initData(em);
- em.getTransaction().commit();
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException();
- } finally {
- if (em.getTransaction().isActive()) {
- em.getTransaction().rollback();
- }
- }
- threadExecution(em);
- try {
- Thread.sleep(7000L);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("##########################Test with semaphores - begin###########################");
- EntityManager emSemaphore = emfSemaphore.createEntityManager();
- verifySemaphoreProperties();
- threadExecution(emSemaphore);
- System.out.println("##########################Test with semaphores - end###########################");
- }
-
- private void threadExecution(EntityManager em) {
- ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(NO_OF_THREADS);
- for (int i = 1; i <= NO_OF_THREADS; i++) {
- Thread thread = new Thread(new MainThread(container, emf, em));
- thread.setName("MainThread: " + i);
- executor.execute(thread);
- }
- executor.shutdown();
- // Wait for everything to finish.
- try {
- executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- Assert.fail();
- }
- }
-
- @Before
- public void initContainer() {
- container = SeContainerInitializer.newInstance().initialize();
- eventProducer = container.select(EventProducer.class).get();
- }
-
- private static void initData(EntityManager em) {
- for (int i = 1, j = 1; i <= RECORDS_NO; i++, j = j +2) {
- CacheDeadLockDetectionMaster cacheDeadLockDetectionMaster = new CacheDeadLockDetectionMaster(i, "M" + i);
- CacheDeadLockDetectionDetail cacheDeadLockDetectionDetail1 = new CacheDeadLockDetectionDetail(j, "D" + j);
- CacheDeadLockDetectionDetail cacheDeadLockDetectionDetail2 = new CacheDeadLockDetectionDetail(j + 1, "D" + (j + 1));
- cacheDeadLockDetectionDetail1.setMaster(cacheDeadLockDetectionMaster);
- cacheDeadLockDetectionDetail2.setMaster(cacheDeadLockDetectionMaster);
- em.persist(cacheDeadLockDetectionMaster);
- em.persist(cacheDeadLockDetectionDetail1);
- em.persist(cacheDeadLockDetectionDetail2);
- }
- }
-
-
- public void setup() {
- EntityManager em = emf.createEntityManager();
- try {
- DatabaseSession session = ((EntityManagerImpl) em).getDatabaseSession();
- try {
- session.executeNonSelectingSQL("DROP TABLE cachedeadlock_detail");
- } catch (Exception ignore) {
- }
- try {
- session.executeNonSelectingSQL("DROP TABLE cachedeadlock_master");
- } catch (Exception ignore) {
- }
- try {
- session.executeNonSelectingSQL("CREATE TABLE cachedeadlock_master (id integer NOT NULL, name varchar(200), PRIMARY KEY(id))");
- session.executeNonSelectingSQL("CREATE TABLE cachedeadlock_detail (id integer NOT NULL, id_fk integer , name varchar(200), PRIMARY KEY(id))");
- session.executeNonSelectingSQL("ALTER TABLE cachedeadlock_detail ADD CONSTRAINT fk_cachedeadlock_detail FOREIGN KEY ( id_fk ) REFERENCES cachedeadlock_master (ID)");
- } catch (Exception ignore) {
- }
- } finally {
- if (em.getTransaction().isActive()) {
- em.getTransaction().rollback();
- }
- if (em.isOpen()) {
- em.close();
- }
- }
- }
-
- private void verifyPersistenceProperties() {
- assertEquals(1L, ConcurrencyUtil.SINGLETON.getAcquireWaitTime());
- assertEquals(2L, ConcurrencyUtil.SINGLETON.getMaxAllowedSleepTime());
- assertEquals(800L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceTinyDumpLogMessage());
- assertEquals(1000L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceMassiveDumpLogMessage());
- assertEquals(5L, ConcurrencyUtil.SINGLETON.getBuildObjectCompleteWaitTime());
- assertTrue(ConcurrencyUtil.SINGLETON.isAllowTakingStackTraceDuringReadLockAcquisition());
- assertTrue(ConcurrencyUtil.SINGLETON.isAllowConcurrencyExceptionToBeFiredUp());
- assertTrue(ConcurrencyUtil.SINGLETON.isAllowInterruptedExceptionFired());
- }
-
- private void verifySemaphoreProperties() {
- assertEquals(1L, ConcurrencyUtil.SINGLETON.getAcquireWaitTime());
- assertEquals(2L, ConcurrencyUtil.SINGLETON.getMaxAllowedSleepTime());
- assertEquals(1000L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceTinyDumpLogMessage());
- assertEquals(2000L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceMassiveDumpLogMessage());
- assertTrue(ConcurrencyUtil.SINGLETON.isAllowTakingStackTraceDuringReadLockAcquisition());
- assertTrue(ConcurrencyUtil.SINGLETON.isAllowConcurrencyExceptionToBeFiredUp());
- assertTrue(ConcurrencyUtil.SINGLETON.isAllowInterruptedExceptionFired());
- assertTrue(ConcurrencyUtil.SINGLETON.isUseSemaphoreInObjectBuilder());
- assertEquals(5L, ConcurrencyUtil.SINGLETON.getNoOfThreadsAllowedToObjectBuildInParallel());
- assertTrue(ConcurrencyUtil.SINGLETON.isUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks());
- assertEquals(6L, ConcurrencyUtil.SINGLETON.getNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel());
- assertEquals(7L, ConcurrencyUtil.SINGLETON.getConcurrencySemaphoreMaxTimePermit());
- assertEquals(8L, ConcurrencyUtil.SINGLETON.getConcurrencySemaphoreLogTimeout());
- }
-}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/persistence.xml b/jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/persistence.xml
index dda1d7565bd..54b559b24be 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/persistence.xml
+++ b/jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/persistence.xml
@@ -60,44 +60,4 @@
true
-
-
- org.eclipse.persistence.jpa.PersistenceProvider
- org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster
- org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionDetail
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.eclipse.persistence.jpa.PersistenceProvider
- org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster
- org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionDetail
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/pom.xml b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/pom.xml
new file mode 100644
index 00000000000..ce6127331eb
--- /dev/null
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/pom.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+ org.eclipse.persistence.jpa.testapps
+ org.eclipse.persistence
+ 5.0.0-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+
+ org.eclipse.persistence.jpa.testapps.deadlock.diagnostic
+
+ Test - deadlock diagnostic framework
+
+
+
+
+
+
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+
+
+ org.jboss.weld.se
+ weld-se-core
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+
+ get-test-classpath-to-properties
+ process-test-classes
+
+
+
+
+ org.carlspring.maven
+ derby-maven-plugin
+
+
+ start-derby
+ process-test-classes
+
+
+ stop-derby
+ prepare-package
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ default-test
+
+ -javaagent:${org.eclipse.persistence:org.eclipse.persistence.jpa:jar} @{argLine}
+
+ CacheDeadLockDetectionTest*
+
+
+
+
+ dead-lock-managers-test
+
+ test
+
+
+
+ CacheDeadLockManagersTest*
+
+
+
+ ${db.driver}
+ ${db.url}
+ ${db.user}
+ ${db.pwd}
+ ${db.platform}
+
+
+
+
+
+
+
+
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/model/CacheDeadLockDetectionDetail.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/CacheDeadLockDetectionDetail.java
similarity index 85%
rename from jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/model/CacheDeadLockDetectionDetail.java
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/CacheDeadLockDetectionDetail.java
index f209cbc277d..2ca9a7986a2 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/model/CacheDeadLockDetectionDetail.java
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/CacheDeadLockDetectionDetail.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -12,22 +12,25 @@
// Contributors:
// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock.model;
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic;
import jakarta.persistence.*;
@Entity
-@Table(name = "cachedeadlock_detail")
+@Table(name = "CACHEDEADLOCK_DETAIL")
@Cacheable(true)
@NamedQuery(name="DetailEntity.findById", query="SELECT t FROM CacheDeadLockDetectionDetail t WHERE t.id = :id")
public class CacheDeadLockDetectionDetail {
+
@Id
+ @Column(name = "ID")
private long id;
+ @Column(name = "NAME")
private String name;
@ManyToOne
- @JoinColumn(name = "id_fk")
+ @JoinColumn(name = "CACHEDEADLOCK_MASTER_FK")
private CacheDeadLockDetectionMaster master;
public CacheDeadLockDetectionDetail() {
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/model/CacheDeadLockDetectionMaster.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/CacheDeadLockDetectionMaster.java
similarity index 85%
rename from jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/model/CacheDeadLockDetectionMaster.java
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/CacheDeadLockDetectionMaster.java
index 6505b96c1ee..173a231393d 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/model/CacheDeadLockDetectionMaster.java
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/CacheDeadLockDetectionMaster.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -12,20 +12,23 @@
// Contributors:
// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock.model;
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic;
import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
-@Table(name = "cachedeadlock_master")
+@Table(name = "CACHEDEADLOCK_MASTER")
@Cacheable(true)
@NamedQuery(name="MasterEntity.findById", query="SELECT t FROM CacheDeadLockDetectionMaster t WHERE t.id = :id")
public class CacheDeadLockDetectionMaster {
+
@Id
+ @Column(name = "ID")
private long id;
+ @Column(name = "NAME")
private String name;
private List details = new ArrayList<>();
@@ -60,7 +63,7 @@ public void setName(String name) {
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "master", cascade = CascadeType.ALL)
- @JoinColumn(name = "id_fk", referencedColumnName = "id")
+ @JoinColumn(name = "CACHEDEADLOCK_MASTER_FK", referencedColumnName = "ID")
public List getDetails() {
return details;
}
diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/DeadLockDiagnosticTableCreator.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/DeadLockDiagnosticTableCreator.java
new file mode 100644
index 00000000000..035707a9fe3
--- /dev/null
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/DeadLockDiagnosticTableCreator.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation from Oracle TopLink
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic;
+
+import org.eclipse.persistence.tools.schemaframework.FieldDefinition;
+import org.eclipse.persistence.tools.schemaframework.ForeignKeyConstraint;
+import org.eclipse.persistence.tools.schemaframework.TableDefinition;
+
+public class DeadLockDiagnosticTableCreator extends org.eclipse.persistence.tools.schemaframework.TableCreator {
+
+ public DeadLockDiagnosticTableCreator() {
+ setName("DeadLockDiagnostic");
+
+ addTableDefinition(buildCACHEDEADLOCK_MASTERTable());
+ addTableDefinition(buildCACHEDEADLOCK_DETAILTable());
+ }
+
+ public TableDefinition buildCACHEDEADLOCK_MASTERTable() {
+ TableDefinition table = new TableDefinition();
+ table.setName("CACHEDEADLOCK_MASTER");
+
+ FieldDefinition fieldID = new FieldDefinition();
+ fieldID.setName("ID");
+ fieldID.setTypeName("NUMBER");
+ fieldID.setSize(0);
+ fieldID.setSubSize(0);
+ fieldID.setIsPrimaryKey(true);
+ fieldID.setIsIdentity(false);
+ fieldID.setUnique(false);
+ fieldID.setShouldAllowNull(false);
+ table.addField(fieldID);
+
+ FieldDefinition fieldNAME = new FieldDefinition();
+ fieldNAME.setName("NAME");
+ fieldNAME.setTypeName("VARCHAR");
+ fieldNAME.setSize(400);
+ fieldNAME.setShouldAllowNull(true);
+ fieldNAME.setIsPrimaryKey(false);
+ fieldNAME.setUnique(false);
+ fieldNAME.setIsIdentity(false);
+ table.addField(fieldNAME);
+
+ return table;
+ }
+
+ public TableDefinition buildCACHEDEADLOCK_DETAILTable() {
+ TableDefinition table = new TableDefinition();
+ table.setName("CACHEDEADLOCK_DETAIL");
+
+ FieldDefinition fieldID = new FieldDefinition();
+ fieldID.setName("ID");
+ fieldID.setTypeName("NUMBER");
+ fieldID.setSize(0);
+ fieldID.setSubSize(0);
+ fieldID.setIsPrimaryKey(true);
+ fieldID.setIsIdentity(false);
+ fieldID.setUnique(false);
+ fieldID.setShouldAllowNull(false);
+ table.addField(fieldID);
+
+ FieldDefinition fieldNAME = new FieldDefinition();
+ fieldNAME.setName("NAME");
+ fieldNAME.setTypeName("VARCHAR");
+ fieldNAME.setSize(400);
+ fieldNAME.setShouldAllowNull(true);
+ fieldNAME.setIsPrimaryKey(false);
+ fieldNAME.setUnique(false);
+ fieldNAME.setIsIdentity(false);
+ table.addField(fieldNAME);
+
+ FieldDefinition fieldCACHEDEADLOCK_MASTER_FK = new FieldDefinition();
+ fieldCACHEDEADLOCK_MASTER_FK.setName("CACHEDEADLOCK_MASTER_FK");
+ fieldCACHEDEADLOCK_MASTER_FK.setTypeName("NUMBER");
+ fieldCACHEDEADLOCK_MASTER_FK.setSize(0);
+ fieldCACHEDEADLOCK_MASTER_FK.setSubSize(0);
+ fieldCACHEDEADLOCK_MASTER_FK.setIsPrimaryKey(false);
+ fieldCACHEDEADLOCK_MASTER_FK.setIsIdentity(false);
+ fieldCACHEDEADLOCK_MASTER_FK.setUnique(false);
+ fieldCACHEDEADLOCK_MASTER_FK.setShouldAllowNull(true);
+ table.addField(fieldCACHEDEADLOCK_MASTER_FK);
+
+ ForeignKeyConstraint foreignKeyM_CACHEDEADLOCK_MASTER = new ForeignKeyConstraint();
+ foreignKeyM_CACHEDEADLOCK_MASTER.setName("M_CACHEDEADLOCK_MASTER_FK");
+ foreignKeyM_CACHEDEADLOCK_MASTER.setTargetTable("CACHEDEADLOCK_MASTER");
+ foreignKeyM_CACHEDEADLOCK_MASTER.addSourceField("CACHEDEADLOCK_MASTER_FK");
+ foreignKeyM_CACHEDEADLOCK_MASTER.addTargetField("ID");
+ table.addForeignKeyConstraint(foreignKeyM_CACHEDEADLOCK_MASTER);
+
+ return table;
+ }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/MainThread.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/MainThread.java
similarity index 85%
rename from jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/MainThread.java
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/MainThread.java
index c7bdf72e143..006268f98a4 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/MainThread.java
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/MainThread.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -12,11 +12,9 @@
// Contributors:
// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock;
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic;
-import org.eclipse.persistence.jpa.test.cachedeadlock.cdi.event.EventProducer;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionDetail;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.event.EventProducer;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.inject.Inject;
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventObserver.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventObserver.java
similarity index 81%
rename from jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventObserver.java
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventObserver.java
index fb2951d6db2..41f06d70db0 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventObserver.java
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventObserver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -12,10 +12,10 @@
// Contributors:
// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock.cdi.event;
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.event;
-import org.eclipse.persistence.jpa.test.cachedeadlock.MainThread;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.MainThread;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventProducer.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventProducer.java
similarity index 68%
rename from jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventProducer.java
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventProducer.java
index 6f1a1945830..4471d821be7 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventProducer.java
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventProducer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -12,9 +12,9 @@
// Contributors:
// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock.cdi.event;
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.event;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster;
public interface EventProducer {
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventProducerImpl.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventProducerImpl.java
similarity index 76%
rename from jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventProducerImpl.java
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventProducerImpl.java
index bfbf42b05b3..1416fe6480d 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/cachedeadlock/cdi/event/EventProducerImpl.java
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/java/org/eclipse/persistence/testing/models/jpa/deadlock/diagnostic/event/EventProducerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -12,9 +12,9 @@
// Contributors:
// Oracle - initial API and implementation
-package org.eclipse.persistence.jpa.test.cachedeadlock.cdi.event;
+package org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.event;
-import org.eclipse.persistence.jpa.test.cachedeadlock.model.CacheDeadLockDetectionMaster;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster;
import jakarta.enterprise.event.Event;
import jakarta.enterprise.inject.Any;
diff --git a/jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/beans.xml b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/resources/META-INF/beans.xml
similarity index 89%
rename from jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/beans.xml
rename to jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/resources/META-INF/beans.xml
index 0ea132eff10..b54469f18ad 100644
--- a/jpa/eclipselink.jpa.test.jse/src/it/resources/META-INF/beans.xml
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/main/resources/META-INF/beans.xml
@@ -1,7 +1,7 @@
+
+
+
+
+ org.eclipse.persistence.jpa.PersistenceProvider
+ org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster
+ org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionDetail
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.persistence.jpa.PersistenceProvider
+ org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster
+ org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionDetail
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/CacheDeadLockDetectionTest.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/CacheDeadLockDetectionTest.java
new file mode 100644
index 00000000000..9db2003bca4
--- /dev/null
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/CacheDeadLockDetectionTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation
+package org.eclipse.persistence.testing.tests.jpa.deadlock.diagnostic;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import jakarta.enterprise.inject.se.SeContainer;
+import jakarta.enterprise.inject.se.SeContainerInitializer;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.Persistence;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.junit.Assert;
+
+import org.eclipse.persistence.internal.sessions.AbstractSession;
+import org.eclipse.persistence.jpa.JpaEntityManager;
+import org.eclipse.persistence.logging.AbstractSessionLog;
+
+import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
+import org.eclipse.persistence.testing.framework.jpa.junit.JUnitTestCase;
+import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionDetail;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.DeadLockDiagnosticTableCreator;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.MainThread;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.event.EventProducer;
+
+public class CacheDeadLockDetectionTest extends JUnitTestCase {
+
+ public static final int RECORDS_NO = 10;
+ public static final int NO_OF_THREADS = 100;
+
+ SeContainer container;
+
+ EventProducer eventProducer;
+
+ public CacheDeadLockDetectionTest() {
+ }
+
+ public CacheDeadLockDetectionTest(String name) {
+ super(name);
+ setPuName(getPersistenceUnitName());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("CacheDeadLockDetectionTest");
+ suite.addTest(new CacheDeadLockDetectionTest("testSetup"));
+ suite.addTest(new CacheDeadLockDetectionTest("testVerifyPersistenceAndBasicLogOutput"));
+ suite.addTest(new CacheDeadLockDetectionTest("testVerifySemaphorePersistenceProperties"));
+ return suite;
+ }
+
+ /**
+ * The setup is done as a test, both to record its failure, and to allow
+ * execution in the server.
+ */
+ public void testSetup() {
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("cachedeadlockdetection-pu", JUnitTestCaseHelper.getDatabaseProperties());
+ EntityManager em = emf.createEntityManager();
+ new DeadLockDiagnosticTableCreator().replaceTables(((JpaEntityManager)em).getServerSession());
+ clearCache("cachedeadlockdetection-pu");
+ try {
+ em.getTransaction().begin();
+ initData(em);
+ em.getTransaction().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException();
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ if (em.isOpen()) {
+ em.close();
+ }
+ if (emf.isOpen()) {
+ emf.close();
+ }
+ }
+ }
+
+ public void testVerifyPersistenceAndBasicLogOutput() {
+ initContainer();
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("cachedeadlockdetection-pu", JUnitTestCaseHelper.getDatabaseProperties());
+ EntityManager em = emf.createEntityManager();
+ AbstractSession serverSession = ((JpaEntityManager)em).getServerSession();
+ LogWrapper logWrapper = new LogWrapper();
+ serverSession.setSessionLog(logWrapper);
+ AbstractSessionLog.setLog(logWrapper);
+ verifyPersistenceProperties();
+ threadExecution(em, emf);
+ try {
+ Thread.sleep(7000L);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ if (em.isOpen()) {
+ em.close();
+ }
+ if (emf.isOpen()) {
+ emf.close();
+ }
+ closeContainer();
+ }
+ //Check if at least one log message is generated
+ assertTrue(logWrapper.getMessageCount("Stuck thread problem: unique tiny message number") > 0);
+ assertTrue(logWrapper.getMessageCount("Start full concurrency manager state \\(massive\\) dump No") > 0);
+ }
+
+ public void testVerifySemaphorePersistenceProperties() {
+ EntityManagerFactory emfSemaphore = Persistence.createEntityManagerFactory("cachedeadlocksemaphore-pu", JUnitTestCaseHelper.getDatabaseProperties());
+ EntityManager emSemaphore = emfSemaphore.createEntityManager();
+ verifySemaphoreProperties();
+ }
+
+ private void initContainer() {
+ container = SeContainerInitializer.newInstance().initialize();
+ eventProducer = container.select(EventProducer.class).get();
+ }
+
+ private void closeContainer() {
+ if (container != null && container.isRunning()) {
+ container.close();
+ }
+ }
+
+ private void threadExecution(EntityManager em, EntityManagerFactory emf) {
+ ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(NO_OF_THREADS);
+ for (int i = 1; i <= NO_OF_THREADS; i++) {
+ Thread thread = new Thread(new MainThread(container, emf, em));
+ thread.setName("MainThread: " + i);
+ executor.execute(thread);
+ }
+ executor.shutdown();
+ // Wait for everything to finish.
+ try {
+ if (!executor.awaitTermination(10000, TimeUnit.MILLISECONDS)) {
+ executor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ executor.shutdownNow();
+ e.printStackTrace();
+ Assert.fail();
+ }
+ }
+
+ private static void initData(EntityManager em) {
+ for (int i = 1, j = 1; i <= RECORDS_NO; i++, j = j + 2) {
+ CacheDeadLockDetectionMaster cacheDeadLockDetectionMaster = new CacheDeadLockDetectionMaster(i, "M" + i);
+ CacheDeadLockDetectionDetail cacheDeadLockDetectionDetail1 = new CacheDeadLockDetectionDetail(j, "D" + j);
+ CacheDeadLockDetectionDetail cacheDeadLockDetectionDetail2 = new CacheDeadLockDetectionDetail(j + 1, "D" + (j + 1));
+ cacheDeadLockDetectionDetail1.setMaster(cacheDeadLockDetectionMaster);
+ cacheDeadLockDetectionDetail2.setMaster(cacheDeadLockDetectionMaster);
+ em.persist(cacheDeadLockDetectionMaster);
+ em.persist(cacheDeadLockDetectionDetail1);
+ em.persist(cacheDeadLockDetectionDetail2);
+ }
+ }
+
+ private void verifyPersistenceProperties() {
+ Assert.assertEquals(1L, ConcurrencyUtil.SINGLETON.getAcquireWaitTime());
+ Assert.assertEquals(2L, ConcurrencyUtil.SINGLETON.getMaxAllowedSleepTime());
+ Assert.assertEquals(800L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceTinyDumpLogMessage());
+ Assert.assertEquals(1000L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceMassiveDumpLogMessage());
+ Assert.assertEquals(5L, ConcurrencyUtil.SINGLETON.getBuildObjectCompleteWaitTime());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isAllowTakingStackTraceDuringReadLockAcquisition());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isAllowConcurrencyExceptionToBeFiredUp());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isAllowInterruptedExceptionFired());
+ }
+
+ private void verifySemaphoreProperties() {
+ Assert.assertEquals(1L, ConcurrencyUtil.SINGLETON.getAcquireWaitTime());
+ Assert.assertEquals(2L, ConcurrencyUtil.SINGLETON.getMaxAllowedSleepTime());
+ Assert.assertEquals(1000L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceTinyDumpLogMessage());
+ Assert.assertEquals(2000L, ConcurrencyUtil.SINGLETON.getMaxAllowedFrequencyToProduceMassiveDumpLogMessage());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isAllowTakingStackTraceDuringReadLockAcquisition());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isAllowConcurrencyExceptionToBeFiredUp());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isAllowInterruptedExceptionFired());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isUseSemaphoreInObjectBuilder());
+ Assert.assertEquals(5L, ConcurrencyUtil.SINGLETON.getNoOfThreadsAllowedToObjectBuildInParallel());
+ Assert.assertTrue(ConcurrencyUtil.SINGLETON.isUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks());
+ Assert.assertEquals(6L, ConcurrencyUtil.SINGLETON.getNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel());
+ Assert.assertEquals(7L, ConcurrencyUtil.SINGLETON.getConcurrencySemaphoreMaxTimePermit());
+ Assert.assertEquals(8L, ConcurrencyUtil.SINGLETON.getConcurrencySemaphoreLogTimeout());
+ }
+}
diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/CacheDeadLockManagersTest.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/CacheDeadLockManagersTest.java
new file mode 100644
index 00000000000..9881f802b91
--- /dev/null
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/CacheDeadLockManagersTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation
+package org.eclipse.persistence.testing.tests.jpa.deadlock.diagnostic;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.Persistence;
+import jakarta.persistence.Query;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.eclipse.persistence.descriptors.ClassDescriptor;
+import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
+import org.eclipse.persistence.internal.helper.WriteLockManager;
+import org.eclipse.persistence.internal.identitymaps.CacheKey;
+import org.eclipse.persistence.internal.jpa.EJBQueryImpl;
+import org.eclipse.persistence.internal.sessions.AbstractSession;
+import org.eclipse.persistence.jpa.JpaEntityManager;
+import org.eclipse.persistence.logging.AbstractSessionLog;
+import org.eclipse.persistence.queries.ObjectBuildingQuery;
+import org.eclipse.persistence.testing.framework.jpa.junit.JUnitTestCase;
+import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionDetail;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.CacheDeadLockDetectionMaster;
+import org.eclipse.persistence.testing.models.jpa.deadlock.diagnostic.DeadLockDiagnosticTableCreator;
+
+import java.util.Map;
+
+public class CacheDeadLockManagersTest extends JUnitTestCase {
+
+ public static final int RECORDS_NO = 10;
+
+ public CacheDeadLockManagersTest() {
+ }
+
+ public CacheDeadLockManagersTest(String name) {
+ super(name);
+ setPuName(getPersistenceUnitName());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("CacheDeadLockDetectionTest");
+ suite.addTest(new CacheDeadLockManagersTest("testSetup"));
+ suite.addTest(new CacheDeadLockManagersTest("testWriteLockManagerAcquireLocksForClone"));
+ return suite;
+ }
+
+ /**
+ * The setup is done as a test, both to record its failure, and to allow
+ * execution in the server.
+ */
+ public void testSetup() {
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("cachedeadlockdetection-pu", JUnitTestCaseHelper.getDatabaseProperties());
+ EntityManager em = emf.createEntityManager();
+ new DeadLockDiagnosticTableCreator().replaceTables(((JpaEntityManager)em).getServerSession());
+ clearCache("cachedeadlockdetection-pu");
+ try {
+ em.getTransaction().begin();
+ initData(em);
+ em.getTransaction().commit();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException();
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ if (em.isOpen()) {
+ em.close();
+ }
+ if (emf.isOpen()) {
+ emf.close();
+ }
+ }
+ }
+
+ public void testWriteLockManagerAcquireLocksForClone() {
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("cachedeadlockdetection-pu", JUnitTestCaseHelper.getDatabaseProperties());
+ EntityManager em = emf.createEntityManager();
+ AbstractSession serverSession = ((JpaEntityManager)em).getServerSession();
+ LogWrapper logWrapper = new LogWrapper();
+ serverSession.setSessionLog(logWrapper);
+ AbstractSessionLog.setLog(logWrapper);
+ try {
+ Long primaryKey = Long.valueOf(1L);
+ Query query = em.createQuery("SELECT c FROM CacheDeadLockDetectionMaster c WHERE c.id = :id");
+ query.setParameter("id", primaryKey);
+ CacheDeadLockDetectionMaster result = (CacheDeadLockDetectionMaster) query.getSingleResult();
+ ClassDescriptor descriptor = serverSession.getDescriptor(CacheDeadLockDetectionMaster.class);
+ CacheKey cacheKey = serverSession.retrieveCacheKey(primaryKey, descriptor, null, (ObjectBuildingQuery) ((EJBQueryImpl)query).getDatabaseQuery());
+ cacheKey.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
+ //Tricky part with some negative value to simulate deadlock detection.
+ ConcurrencyUtil.SINGLETON.setMaxAllowedSleepTime(-1000000);
+ ConcurrencyUtil.SINGLETON.setAllowConcurrencyExceptionToBeFiredUp(true);
+ WriteLockManager writeLockManager = new WriteLockManager();
+ Map map = writeLockManager.acquireLocksForClone(result, descriptor, cacheKey, serverSession);
+ } catch (Exception e) {
+ assertEquals(2, logWrapper.getMessageCount(WriteLockManager.class.getName() + ".acquireLocksForClone"));
+ } finally {
+ if (em != null) {
+ if (em.isOpen()) {
+ em.close();
+ }
+ }
+ }
+ }
+
+ private static void initData(EntityManager em) {
+ for (int i = 1, j = 1; i <= RECORDS_NO; i++, j = j + 2) {
+ CacheDeadLockDetectionMaster cacheDeadLockDetectionMaster = new CacheDeadLockDetectionMaster(i, "M" + i);
+ CacheDeadLockDetectionDetail cacheDeadLockDetectionDetail1 = new CacheDeadLockDetectionDetail(j, "D" + j);
+ CacheDeadLockDetectionDetail cacheDeadLockDetectionDetail2 = new CacheDeadLockDetectionDetail(j + 1, "D" + (j + 1));
+ cacheDeadLockDetectionDetail1.setMaster(cacheDeadLockDetectionMaster);
+ cacheDeadLockDetectionDetail2.setMaster(cacheDeadLockDetectionMaster);
+ em.persist(cacheDeadLockDetectionMaster);
+ em.persist(cacheDeadLockDetectionDetail1);
+ em.persist(cacheDeadLockDetectionDetail2);
+ }
+ }
+}
diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/LogWrapper.java b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/LogWrapper.java
new file mode 100644
index 00000000000..f6e0d481fad
--- /dev/null
+++ b/jpa/eclipselink.jpa.testapps/jpa.test.diagnostic.deadlock/src/test/java/org/eclipse/persistence/testing/tests/jpa/deadlock/diagnostic/LogWrapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+// Contributors:
+// Oracle - initial API and implementation from Oracle TopLink
+package org.eclipse.persistence.testing.tests.jpa.deadlock.diagnostic;
+
+import org.eclipse.persistence.logging.DefaultSessionLog;
+import org.eclipse.persistence.logging.SessionLogEntry;
+
+import java.io.StringWriter;
+import java.util.regex.Pattern;
+
+//Simple log handler which counts selected messages.
+public class LogWrapper extends DefaultSessionLog {
+
+ private StringWriter sw = new StringWriter();
+
+ public LogWrapper() {
+ super.setWriter(sw);
+ }
+
+
+ @Override
+ public synchronized void log(SessionLogEntry entry) {
+ super.log(entry);
+ }
+
+ @Override
+ public boolean shouldLog(int level, String category) {
+ return true;
+ }
+
+ public long getMessageCount(String checkedMessage) {
+ String logOutput = sw.toString();
+ return Pattern.compile(checkedMessage)
+ .matcher(logOutput)
+ .results()
+ .count();
+ }
+}
diff --git a/jpa/eclipselink.jpa.testapps/pom.xml b/jpa/eclipselink.jpa.testapps/pom.xml
index 0fc9582dbd3..60c1859c8fe 100644
--- a/jpa/eclipselink.jpa.testapps/pom.xml
+++ b/jpa/eclipselink.jpa.testapps/pom.xml
@@ -306,6 +306,7 @@
jpa.test.ddlgeneration
jpa.test.delimited
jpa.test.diagnostic
+ jpa.test.diagnostic.deadlock
jpa.test.extensibility
jpa.test.fetchgroups
jpa.test.fieldaccess.advanced