blob: 5aa54b833670f5c623d5d0a470e7c2409b5c53af [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.cache;
import java.util.Vector;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.tests.clientserver.Server;
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 TestCase {
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;
}
}
}