blob: 37d447b567181b3531c3d07d1d74aedbe801900d [file] [log] [blame]
/*
* Copyright (c) 1998, 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.identitymaps;
import java.util.Vector;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.testing.tests.clientserver.Server;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.bigbad.*;
/**
* This test is set up to have one thread build a BigBadObject instance, while multiple other threads
* attempt to access the same instance from the cache. The test fails if any of the threads access
* an incomplete instance of the BigBadObject object - where it has been only partially built. Only
* the "number02" attribute is checked, as all mapping weights are changed so this mapping is
* built last. Built to test bug 4772232
*/
public class ConcurrentReadBigBadObjectTest extends AutoVerifyTestCase {
public ConcurrentReadBigBadObjectTest() {
}
BigBadObject referenceObject;
protected int numOftries = 300;
protected int numOfThreads = 10;
protected boolean failed;
protected Server server;
protected int OrigDirectMapWeight;
@Override
public void setup() throws Exception {
DatabaseLogin login;
login = (DatabaseLogin)getSession().getLogin().clone();
server = new Server(login);
server.serverSession.setLogLevel(getSession().getLogLevel());
server.serverSession.setLog(getSession().getLog());
server.copyDescriptors(getSession());
ClassDescriptor d = (server.serverSession).getClassDescriptor(BigBadObject.class);
DatabaseMapping m;
Vector<DatabaseMapping> v = d.getMappings();
int mappings = v.size();
int i = 0;
while (i < mappings) {
m = v.get(i);
m.setWeight(Integer.MAX_VALUE - 1);
i++;
}
m = d.getMappingForAttributeName("number02");
m.setWeight(Integer.MAX_VALUE);
server.login();
server.serverSession.setLogLevel(getSession().getLogLevel());
server.serverSession.setLog(getSession().getLog());
}
@Override
public void reset() throws Exception {
server.logout();
}
@Override
public void test() {
failed = false;
referenceObject = (BigBadObject)this.getSession().readObject(BigBadObject.class);
Reader[] threadList = new Reader[numOfThreads];
for (int i = 0; i < numOfThreads; ) {
threadList[i] = new Reader(referenceObject, server.serverSession.acquireClientSession(), ++i);
}
for (int i = 0; i < numOfThreads; i++) {
threadList[i].start();
}
try {
for (int i = 0; i < numOfThreads; i++) {
threadList[i].join();
}
} catch (InterruptedException ex) {
}
int count = 0;
while (!failed && count < numOfThreads) {
if (threadList[count].exception != null) {
throw threadList[count].exception;
}
failed = threadList[count].hadError();
count++;
}
if (failed) {
throw new TestErrorException("Test failed, getFromIdentityMap returned an object before it was finished being built");
}
}
/**
* Threads to read/access the cache numOftries times. Only thread 1 will initialize the cache and
* read the BigBadObject object instance.
*/
private class Reader extends Thread {
protected BigBadObject referenceObject, readObject;
protected Session session;
public int thread;
public int counter;
public RuntimeException exception;
protected boolean experienceError = false;
public Reader(BigBadObject object, Session session, int thread) {
this.referenceObject = object;
this.session = session;
this.thread = thread;
counter = 0;
}
@Override
public void run() {
try {
counter = 0;
while (!experienceError && counter < numOftries) {
if (thread == 1) {
session.getIdentityMapAccessor().initializeIdentityMap(BigBadObject.class);
readObject = (BigBadObject)session.readObject(referenceObject);
} else {
readObject = (BigBadObject)session.getIdentityMapAccessor().getFromIdentityMap(referenceObject);
}
if ((readObject != null) &&
((readObject.number02 == null) || (!readObject.number02.equals(referenceObject.number02)))) {
this.experienceError = true;
}
counter++;
}
} catch (RuntimeException ex) {
this.experienceError = true;
this.exception = ex;
}
}
public boolean hadError() {
return experienceError;
}
}
}