| /* |
| * 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.unitofwork; |
| |
| import java.io.Serializable; |
| import java.io.StringWriter; |
| |
| import java.math.BigDecimal; |
| |
| import org.eclipse.persistence.descriptors.RelationalDescriptor; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.mappings.DirectToFieldMapping; |
| import org.eclipse.persistence.testing.tests.unitofwork.ConcurrentReadOnUpdateWithEarlyTransTest; |
| import org.eclipse.persistence.tools.schemaframework.TableDefinition; |
| |
| |
| /** |
| * <p><b>Purpose</b>: Represents the mailing address on an Employee |
| * <p><b>Description</b>: Held in a private 1:1 relationship from Employee |
| * @see Employee |
| */ |
| public class ConcurrentAddress implements Serializable, Cloneable { |
| public BigDecimal id; |
| public String street; |
| public String city; |
| public String province; |
| public String postalCode; |
| public String country; |
| |
| //USED TO DETERMINE WHICH TEST IS RUNNING |
| public static int RUNNING_TEST; |
| |
| //tests |
| public static final int NONE = Integer.MIN_VALUE; |
| public static final int LOCK_ON_CLONE_TEST = 55; |
| public static final int LOCK_ON_CLONE_DEADLOCK = 56; |
| public static final int READ_ON_UPDATE_EARLY_TRANS = 57; |
| public static boolean isForBackup = false; |
| |
| public ConcurrentAddress() { |
| this.city = ""; |
| this.province = ""; |
| this.postalCode = ""; |
| this.street = ""; |
| this.country = ""; |
| } |
| |
| @Override |
| public Object clone() { |
| ConcurrentAddress result = new ConcurrentAddress(); |
| result.id = this.id; |
| result.city = this.city; |
| result.province = this.province; |
| result.postalCode = this.postalCode; |
| result.street = this.street; |
| result.country = this.country; |
| return result; |
| |
| } |
| |
| public String getCity() { |
| return city; |
| } |
| |
| public String getCountry() { |
| try { |
| if (ConcurrentRefreshOnCloneTest.lock != null) { |
| synchronized (ConcurrentRefreshOnCloneTest.lock) { |
| if (!ConcurrentRefreshOnCloneTest.waited) { |
| if (ConcurrentRefreshOnCloneTest.readerWaiting) { |
| ConcurrentRefreshOnCloneTest.lock.notifyAll(); |
| Thread.yield(); |
| } |
| |
| // verify that we are not currently holding an active lock on the system. Which would result in a deadlock |
| if (((AbstractSession)ConcurrentRefreshOnCloneTest.session).getIdentityMapAccessorInstance().getIdentityMapManager().getCacheMutex().getActiveThread() != |
| Thread.currentThread()) { |
| ConcurrentRefreshOnCloneTest.cloneWaiting = true; |
| ConcurrentRefreshOnCloneTest.lock.wait(30000); |
| ConcurrentRefreshOnCloneTest.cloneWaiting = false; |
| } else { |
| //can't lock but let's sleep to simulate a window for refresh |
| Thread.sleep(4000); |
| } |
| ConcurrentRefreshOnCloneTest.waited = true; |
| } |
| } |
| } |
| } catch (Exception ex) { |
| } |
| return country; |
| } |
| |
| /** |
| * Return the persistent identifier of the receiver. |
| */ |
| public BigDecimal getId() { |
| return id; |
| } |
| |
| public String getPostalCode() { |
| return postalCode; |
| } |
| |
| public String getProvince() { |
| //used in the Lock on clone test |
| if ((ConcurrentAddress.RUNNING_TEST == ConcurrentAddress.LOCK_ON_CLONE_TEST) || |
| (ConcurrentAddress.RUNNING_TEST == ConcurrentAddress.LOCK_ON_CLONE_DEADLOCK)) { |
| if (!isForBackup) { |
| synchronized (this) { |
| isForBackup = true; //the next call to this method will be for backup |
| this.notifyAll(); // let refresh update the fields |
| try { |
| this.wait(10000); //wait for refresh to update the fields |
| } catch (InterruptedException ex) { |
| } |
| } |
| } else { |
| isForBackup = false; |
| } |
| } |
| return province; |
| } |
| |
| public String getStreet() { |
| return street; |
| } |
| |
| public void setCity(String city) { |
| this.city = city; |
| } |
| |
| public void setCountry(String country) { |
| this.country = country; |
| } |
| |
| /** |
| * Set the persistent identifier of the receiver. |
| */ |
| public void setId(BigDecimal id) { |
| try { |
| if (ConcurrentAddress.RUNNING_TEST == ConcurrentAddress.READ_ON_UPDATE_EARLY_TRANS) { |
| if (ConcurrentReadOnUpdateWithEarlyTransTest.threadId.get().equals("Writer")) { |
| synchronized (ConcurrentReadOnUpdateWithEarlyTransTest.readAddress) { |
| ConcurrentReadOnUpdateWithEarlyTransTest.readAddress.notify(); // wake up reader. |
| ConcurrentReadOnUpdateWithEarlyTransTest.whosWaiting = |
| ConcurrentReadOnUpdateWithEarlyTransTest.WRITER; |
| ConcurrentReadOnUpdateWithEarlyTransTest.readAddress.wait(30000); |
| } |
| } |
| } else { |
| if (ConcurrentReadOnInsertTest.readAddress != null) { |
| synchronized (ConcurrentReadOnInsertTest.readAddress) { |
| if (ConcurrentReadOnInsertTest.depth <= 0) { |
| ConcurrentReadOnInsertTest.readAddress.notifyAll(); |
| } else { |
| --ConcurrentReadOnInsertTest.depth; |
| } |
| } |
| |
| // make an extra buffer to ensure that the read has time to run |
| Thread.sleep(2000); |
| } |
| } |
| } catch (Exception ex) { |
| } |
| this.id = id; |
| } |
| |
| public void setPostalCode(String postalCode) { |
| this.postalCode = postalCode; |
| } |
| |
| public void setProvince(String province) { |
| this.province = province; |
| } |
| |
| public void setStreet(String street) { |
| this.street = street; |
| } |
| |
| /** |
| * Print the address city and province. |
| */ |
| public String toString() { |
| StringWriter writer = new StringWriter(); |
| |
| writer.write("Address: "); |
| writer.write(this.street); |
| writer.write(", "); |
| writer.write(this.city); |
| writer.write(", "); |
| writer.write(this.province); |
| writer.write(", "); |
| writer.write(this.country); |
| return writer.toString(); |
| } |
| |
| public static TableDefinition tableDefinition() { |
| org.eclipse.persistence.tools.schemaframework.TableDefinition tabledefinition = |
| new org.eclipse.persistence.tools.schemaframework.TableDefinition(); |
| |
| // SECTION: TABLE |
| tabledefinition.setName("CONCURRENT_ADDRESS"); |
| |
| // SECTION: FIELD |
| org.eclipse.persistence.tools.schemaframework.FieldDefinition field = |
| new org.eclipse.persistence.tools.schemaframework.FieldDefinition(); |
| field.setName("ADDRESS_ID"); |
| field.setTypeName("NUMERIC"); |
| field.setSize(15); |
| field.setShouldAllowNull(false); |
| field.setIsPrimaryKey(true); |
| field.setUnique(false); |
| field.setIsIdentity(true); |
| tabledefinition.addField(field); |
| |
| // SECTION: FIELD |
| org.eclipse.persistence.tools.schemaframework.FieldDefinition field1 = |
| new org.eclipse.persistence.tools.schemaframework.FieldDefinition(); |
| field1.setName("P_CODE"); |
| field1.setTypeName("VARCHAR"); |
| field1.setSize(20); |
| field1.setShouldAllowNull(true); |
| field1.setIsPrimaryKey(false); |
| field1.setUnique(false); |
| field1.setIsIdentity(false); |
| tabledefinition.addField(field1); |
| |
| // SECTION: FIELD |
| org.eclipse.persistence.tools.schemaframework.FieldDefinition field2 = |
| new org.eclipse.persistence.tools.schemaframework.FieldDefinition(); |
| field2.setName("CITY"); |
| field2.setTypeName("VARCHAR"); |
| field2.setSize(80); |
| field2.setShouldAllowNull(true); |
| field2.setIsPrimaryKey(false); |
| field2.setUnique(false); |
| field2.setIsIdentity(false); |
| tabledefinition.addField(field2); |
| |
| // SECTION: FIELD |
| org.eclipse.persistence.tools.schemaframework.FieldDefinition field3 = |
| new org.eclipse.persistence.tools.schemaframework.FieldDefinition(); |
| field3.setName("PROVINCE"); |
| field3.setTypeName("VARCHAR"); |
| field3.setSize(80); |
| field3.setShouldAllowNull(true); |
| field3.setIsPrimaryKey(false); |
| field3.setUnique(false); |
| field3.setIsIdentity(false); |
| tabledefinition.addField(field3); |
| |
| // SECTION: FIELD |
| org.eclipse.persistence.tools.schemaframework.FieldDefinition field4 = |
| new org.eclipse.persistence.tools.schemaframework.FieldDefinition(); |
| field4.setName("STREET"); |
| field4.setTypeName("VARCHAR"); |
| field4.setSize(80); |
| field4.setShouldAllowNull(true); |
| field4.setIsPrimaryKey(false); |
| field4.setUnique(false); |
| field4.setIsIdentity(false); |
| tabledefinition.addField(field4); |
| |
| // SECTION: FIELD |
| org.eclipse.persistence.tools.schemaframework.FieldDefinition field5 = |
| new org.eclipse.persistence.tools.schemaframework.FieldDefinition(); |
| field5.setName("COUNTRY"); |
| field5.setTypeName("VARCHAR"); |
| field5.setSize(80); |
| field5.setShouldAllowNull(true); |
| field5.setIsPrimaryKey(false); |
| field5.setUnique(false); |
| field5.setIsIdentity(false); |
| tabledefinition.addField(field5); |
| |
| return tabledefinition; |
| } |
| |
| public static RelationalDescriptor descriptor() { |
| // NOTE: weights are set on the mapping to ensure the order in which they are |
| // accessed by toplink for timing purposes for test ConcurrentRefreshOnCloneTest |
| RelationalDescriptor descriptor = new RelationalDescriptor(); |
| descriptor.setJavaClass(ConcurrentAddress.class); |
| descriptor.addTableName("CONCURRENT_ADDRESS"); |
| descriptor.addPrimaryKeyFieldName("CONCURRENT_ADDRESS.ADDRESS_ID"); |
| |
| // RelationalDescriptor properties. |
| descriptor.useFullIdentityMap(); |
| descriptor.setIdentityMapSize(100); |
| descriptor.setSequenceNumberFieldName("ADDRESS_ID"); |
| descriptor.setSequenceNumberName("ADDRESS_SEQ"); |
| |
| // Query manager. |
| descriptor.getQueryManager().checkCacheForDoesExist(); |
| |
| // Event manager. |
| // Mappings. |
| DirectToFieldMapping cityMapping = new DirectToFieldMapping(); |
| cityMapping.setAttributeName("city"); |
| cityMapping.setFieldName("CONCURRENT_ADDRESS.CITY"); |
| cityMapping.setWeight(Integer.valueOf(10)); |
| descriptor.addMapping(cityMapping); |
| |
| DirectToFieldMapping countryMapping = new DirectToFieldMapping(); |
| countryMapping.setAttributeName("country"); |
| countryMapping.setFieldName("CONCURRENT_ADDRESS.COUNTRY"); |
| countryMapping.setSetMethodName("setCountry"); |
| countryMapping.setGetMethodName("getCountry"); |
| countryMapping.setWeight(Integer.valueOf(9)); |
| descriptor.addMapping(countryMapping); |
| |
| DirectToFieldMapping idMapping = new DirectToFieldMapping(); |
| idMapping.setAttributeName("id"); |
| idMapping.setFieldName("CONCURRENT_ADDRESS.ADDRESS_ID"); |
| idMapping.setSetMethodName("setId"); |
| idMapping.setGetMethodName("getId"); |
| idMapping.setWeight(Integer.valueOf(8)); |
| descriptor.addMapping(idMapping); |
| |
| DirectToFieldMapping postalCodeMapping = new DirectToFieldMapping(); |
| postalCodeMapping.setAttributeName("postalCode"); |
| postalCodeMapping.setFieldName("CONCURRENT_ADDRESS.P_CODE"); |
| postalCodeMapping.setWeight(Integer.valueOf(7)); |
| descriptor.addMapping(postalCodeMapping); |
| |
| DirectToFieldMapping provinceMapping = new DirectToFieldMapping(); |
| provinceMapping.setAttributeName("province"); |
| provinceMapping.setFieldName("CONCURRENT_ADDRESS.PROVINCE"); |
| provinceMapping.setSetMethodName("setProvince"); |
| provinceMapping.setGetMethodName("getProvince"); |
| provinceMapping.setWeight(Integer.valueOf(6)); |
| descriptor.addMapping(provinceMapping); |
| |
| DirectToFieldMapping streetMapping = new DirectToFieldMapping(); |
| streetMapping.setAttributeName("street"); |
| streetMapping.setFieldName("CONCURRENT_ADDRESS.STREET"); |
| streetMapping.setWeight(Integer.valueOf(5)); |
| descriptor.addMapping(streetMapping); |
| |
| return descriptor; |
| } |
| } |