/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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; 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 v = d.getMappings(); int mappings = v.size(); int i = 0; while (i < mappings) { m = (DatabaseMapping)v.get(i); m.setWeight(new Integer(Integer.MAX_VALUE - 1)); i++; } m = d.getMappingForAttributeName("number02"); m.setWeight(new Integer(Integer.MAX_VALUE)); server.login(); server.serverSession.setLogLevel(getSession().getLogLevel()); server.serverSession.setLog(getSession().getLog()); } public void reset() throws Exception { server.logout(); } 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; } 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; } } }