blob: 7e66e944430546667cbaa3eeae8b86107312748c [file] [log] [blame]
/*
* Copyright (c) 2011, 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 from Oracle TopLink
package org.eclipse.persistence.testing.tests.simultaneous;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.testing.framework.AutoVerifyTestCase;
import org.eclipse.persistence.testing.models.employee.domain.Employee;
import org.eclipse.persistence.testing.models.employee.domain.Project;
import org.eclipse.persistence.testing.models.employee.domain.SmallProject;
import org.eclipse.persistence.testing.models.employee.domain.Address;
//see bug 305611
public class AppendLockTest extends AutoVerifyTestCase {
Employee emp = null;
SmallProject project = null;
Address address = null;
public AppendLockTest() {
super();
}
@Override
protected void setup() throws Throwable {
super.setup();
getExecutor().swapServerSession();
UnitOfWork uow = getSession().acquireUnitOfWork();
project = new SmallProject();
uow.registerNewObject(project);
emp = new Employee();
address = new Address();
uow.registerNewObject(address);
uow.registerNewObject(emp);
uow.commit();
}
@Override
protected void test() throws Throwable {
// TODO Auto-generated method stub
super.test();
Thread locker = new Thread(new Locker(getSession(), address));
Thread writer1 = new Thread(new Writer1(getSession(), emp, project, address));
Thread writer2 = new Thread (new Writer2(getSession(), project));
locker.start();
writer1.start();
writer2.start();
writer2.join(60000);
try{
if (writer2.isAlive()){
try{
writer2.interrupt();
writer1.interrupt();
locker.interrupt();
}catch (Exception e) {
}
fail("Bug 9484687 - deadlock occured.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void reset() throws Throwable {
super.reset();
getExecutor().resetSession();
getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
UnitOfWork uow = getSession().acquireUnitOfWork();
this.project = (SmallProject) uow.refreshObject(project);
this.emp = (Employee)uow.refreshObject(emp);
uow.deleteObject(project);
uow.deleteObject(emp);
uow.commit();
}
public static class Writer1 implements Runnable{
protected Project project;
protected Employee emp;
protected Session session;
protected Address address;
public Writer1(Session session, Employee emp, Project project, Address address){
this.session = session;
this.project = project;
this.emp = emp;
this.address =address;
}
@Override
public void run() {
UnitOfWork uow = session.acquireUnitOfWork();
Project p = (Project) uow.readObject(project);
Address address = (Address) uow.readObject(this.address);
Employee emp = (Employee) uow.readObject(this.emp);
emp.setAddress(address);
p.setDescription("SomeBigLongDescription");
((AbstractSession)this.session).getIdentityMapAccessorInstance().getCacheKeyForObject(this.project).setObject(null);
((UnitOfWorkImpl)uow).getCloneToOriginals().remove(p);
synchronized (this.session) {
try {
this.session.notifyAll();
this.session.wait(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
uow.commit();
synchronized (this.session) {
this.session.notifyAll();
}
}
}
public static class Locker implements Runnable{
protected Address address;
protected Session session;
public Locker(Session session, Address address){
this.session = session;
this.address = address;
}
@Override
public void run() {
CacheKey cacheKey = null;
synchronized (this.session) {
try {
this.session.wait(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try{
cacheKey = ((AbstractSession)this.session).getIdentityMapAccessorInstance().acquireLock(this.address.getId(), this.address.getClass(), this.session.getClassDescriptor(this.address), false);
synchronized (this.session) {
this.session.notifyAll();
try {
this.session.wait(5000);
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}finally{
cacheKey.release();
}
}
}
public static class Writer2 implements Runnable{
protected Session session;
protected Project project;
public Writer2(Session session, Project project){
this.session = session;
this.project = project;
}
@Override
public void run() {
synchronized (this.session) {
try {
this.session.wait(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (this.session) {
try {
this.session.wait(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (this.session) {
try {
this.session.wait(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
UnitOfWork uow = this.session.acquireUnitOfWork();
try{
this.project = (Project) uow.refreshObject(this.project); // should block
synchronized (this.session) {
this.session.notifyAll();
}
uow.release();
}catch(Exception ex){
System.out.println("Thread was interrupted");
}
}
}
}