mirror of https://github.com/apache/openjpa.git
OPENJPA-138. Some updates to help with performance of OpenJPA in an application server environment. Details can be found in the OPENJPA-138 Issue.
git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@506230 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7d0839f9ff
commit
e14378f7f3
|
@ -29,6 +29,7 @@ public class JNDIManagedRuntime
|
||||||
implements ManagedRuntime {
|
implements ManagedRuntime {
|
||||||
|
|
||||||
private String _tmLoc = "java:/TransactionManager";
|
private String _tmLoc = "java:/TransactionManager";
|
||||||
|
private static TransactionManager _tm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the location of the {@link TransactionManager} in JNDI.
|
* Return the location of the {@link TransactionManager} in JNDI.
|
||||||
|
@ -44,13 +45,18 @@ public class JNDIManagedRuntime
|
||||||
_tmLoc = name;
|
_tmLoc = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransactionManager getTransactionManager()
|
/**
|
||||||
throws Exception {
|
* Return the cached TransactionManager instance.
|
||||||
Context ctx = new InitialContext();
|
*/
|
||||||
try {
|
public TransactionManager getTransactionManager() throws Exception {
|
||||||
return (TransactionManager) ctx.lookup(_tmLoc);
|
if (_tm == null) {
|
||||||
} finally {
|
Context ctx = new InitialContext();
|
||||||
ctx.close();
|
try {
|
||||||
|
_tm = (TransactionManager) ctx.lookup(_tmLoc);
|
||||||
|
} finally {
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return _tm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,8 @@ public abstract class AbstractBrokerFactory
|
||||||
// configuration
|
// configuration
|
||||||
private final OpenJPAConfiguration _conf;
|
private final OpenJPAConfiguration _conf;
|
||||||
private transient boolean _readOnly = false;
|
private transient boolean _readOnly = false;
|
||||||
private transient RuntimeException _closed = null;
|
private transient boolean _closed = false;
|
||||||
|
private transient RuntimeException _closedException = null;
|
||||||
private Map _userObjects = null;
|
private Map _userObjects = null;
|
||||||
|
|
||||||
// internal lock: spec forbids synchronization on this object
|
// internal lock: spec forbids synchronization on this object
|
||||||
|
@ -267,7 +268,7 @@ public abstract class AbstractBrokerFactory
|
||||||
* Returns true if this broker factory is closed.
|
* Returns true if this broker factory is closed.
|
||||||
*/
|
*/
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return _closed != null;
|
return _closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -297,7 +298,10 @@ public abstract class AbstractBrokerFactory
|
||||||
(_conf.getMetaDataRepositoryInstance());
|
(_conf.getMetaDataRepositoryInstance());
|
||||||
|
|
||||||
_conf.close();
|
_conf.close();
|
||||||
_closed = new IllegalStateException();
|
_closed = true;
|
||||||
|
Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
|
||||||
|
if (log.isTraceEnabled())
|
||||||
|
_closedException = new IllegalStateException();
|
||||||
} finally {
|
} finally {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
@ -546,12 +550,18 @@ public abstract class AbstractBrokerFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw an exception if the factory is closed.
|
* Throw an exception if the factory is closed. The exact message and
|
||||||
|
* content of the exception varies whether TRACE is enabled or not.
|
||||||
*/
|
*/
|
||||||
private void assertOpen() {
|
private void assertOpen() {
|
||||||
if (_closed != null)
|
if (_closed) {
|
||||||
throw new InvalidStateException(_loc.get("closed-factory")).
|
if (_closedException == null) // TRACE not enabled
|
||||||
setCause(_closed);
|
throw new InvalidStateException(_loc
|
||||||
|
.get("closed-factory-notrace"));
|
||||||
|
else
|
||||||
|
throw new InvalidStateException(_loc.get("closed-factory"))
|
||||||
|
.setCause(_closedException);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
|
|
|
@ -63,6 +63,7 @@ import org.apache.openjpa.lib.util.Localizer;
|
||||||
import org.apache.openjpa.lib.util.ReferenceHashMap;
|
import org.apache.openjpa.lib.util.ReferenceHashMap;
|
||||||
import org.apache.openjpa.lib.util.ReferenceHashSet;
|
import org.apache.openjpa.lib.util.ReferenceHashSet;
|
||||||
import org.apache.openjpa.lib.util.ReferenceMap;
|
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||||
|
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||||
import org.apache.openjpa.lib.util.concurrent.ReentrantLock;
|
import org.apache.openjpa.lib.util.concurrent.ReentrantLock;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
@ -138,6 +139,9 @@ public class BrokerImpl
|
||||||
|
|
||||||
private static final Localizer _loc =
|
private static final Localizer _loc =
|
||||||
Localizer.forPackage(BrokerImpl.class);
|
Localizer.forPackage(BrokerImpl.class);
|
||||||
|
// Cache for from/to type assignments
|
||||||
|
private static ConcurrentReferenceHashMap _assignableTypes =
|
||||||
|
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||||
|
|
||||||
// the store manager in use; this may be a decorator such as a
|
// the store manager in use; this may be a decorator such as a
|
||||||
// data cache store manager around the native store manager
|
// data cache store manager around the native store manager
|
||||||
|
@ -215,7 +219,8 @@ public class BrokerImpl
|
||||||
|
|
||||||
// status
|
// status
|
||||||
private int _flags = 0;
|
private int _flags = 0;
|
||||||
private RuntimeException _closed = null;
|
private boolean _closed = false;
|
||||||
|
private RuntimeException _closedException = null;
|
||||||
|
|
||||||
// event managers
|
// event managers
|
||||||
private TransactionEventManager _transEventManager = null;
|
private TransactionEventManager _transEventManager = null;
|
||||||
|
@ -1096,8 +1101,7 @@ public class BrokerImpl
|
||||||
cls));
|
cls));
|
||||||
return PCRegistry.newObjectId(cls, (String) val);
|
return PCRegistry.newObjectId(cls, (String) val);
|
||||||
}
|
}
|
||||||
|
if (isAssignable(meta.getObjectIdType(), val.getClass())) {
|
||||||
if (meta.getObjectIdType().isAssignableFrom(val.getClass())) {
|
|
||||||
if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared())
|
if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared())
|
||||||
return new ObjectId(cls, val);
|
return new ObjectId(cls, val);
|
||||||
return val;
|
return val;
|
||||||
|
@ -1118,6 +1122,37 @@ public class BrokerImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache from/to assignments to avoid Class.isAssignableFrom overhead
|
||||||
|
* @param from the target Class
|
||||||
|
* @param to the Class to test
|
||||||
|
* @return true if the "to" class could be assigned to "from" class
|
||||||
|
*/
|
||||||
|
private boolean isAssignable(Class from, Class to) {
|
||||||
|
boolean isAssignable;
|
||||||
|
ConcurrentReferenceHashMap assignableTo =
|
||||||
|
(ConcurrentReferenceHashMap) _assignableTypes.get(from);
|
||||||
|
|
||||||
|
if (assignableTo != null) { // "to" cache exists...
|
||||||
|
isAssignable = (assignableTo.get(to) != null);
|
||||||
|
if (!isAssignable) { // not in the map yet...
|
||||||
|
isAssignable = from.isAssignableFrom(to);
|
||||||
|
if (isAssignable) {
|
||||||
|
assignableTo.put(to, new Object());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // no "to" cache yet...
|
||||||
|
isAssignable = from.isAssignableFrom(to);
|
||||||
|
if (isAssignable) {
|
||||||
|
assignableTo = new ConcurrentReferenceHashMap(
|
||||||
|
ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||||
|
_assignableTypes.put(from, assignableTo);
|
||||||
|
assignableTo.put(to, new Object());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isAssignable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new state manager for the given oid.
|
* Create a new state manager for the given oid.
|
||||||
*/
|
*/
|
||||||
|
@ -3969,11 +4004,11 @@ public class BrokerImpl
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return _closed != null;
|
return _closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCloseInvoked() {
|
public boolean isCloseInvoked() {
|
||||||
return _closed != null || (_flags & FLAG_CLOSE_INVOKED) != 0;
|
return _closed || (_flags & FLAG_CLOSE_INVOKED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -4055,8 +4090,10 @@ public class BrokerImpl
|
||||||
|
|
||||||
_lm.close();
|
_lm.close();
|
||||||
_store.close();
|
_store.close();
|
||||||
_closed = new IllegalStateException();
|
|
||||||
_flags = 0;
|
_flags = 0;
|
||||||
|
_closed = true;
|
||||||
|
if (_log.isTraceEnabled())
|
||||||
|
_closedException = new IllegalStateException();
|
||||||
|
|
||||||
if (err != null)
|
if (err != null)
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -4246,11 +4283,19 @@ public class BrokerImpl
|
||||||
/////////
|
/////////
|
||||||
// Utils
|
// Utils
|
||||||
/////////
|
/////////
|
||||||
|
/**
|
||||||
|
* Throw an exception if the context is closed. The exact message and
|
||||||
|
* content of the exception varies whether TRACE is enabled or not.
|
||||||
|
*/
|
||||||
public void assertOpen() {
|
public void assertOpen() {
|
||||||
if (_closed != null)
|
if (_closed) {
|
||||||
throw new InvalidStateException(_loc.get("closed"), _closed).
|
if (_closedException == null) // TRACE not enabled
|
||||||
setFatal(true);
|
throw new InvalidStateException(_loc.get("closed-notrace"))
|
||||||
|
.setFatal(true);
|
||||||
|
else
|
||||||
|
throw new InvalidStateException(_loc.get("closed"),
|
||||||
|
_closedException).setFatal(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertActiveTransaction() {
|
public void assertActiveTransaction() {
|
||||||
|
|
|
@ -36,6 +36,8 @@ import org.apache.openjpa.lib.rop.ResultObjectProvider;
|
||||||
import org.apache.openjpa.lib.rop.SimpleResultList;
|
import org.apache.openjpa.lib.rop.SimpleResultList;
|
||||||
import org.apache.openjpa.lib.rop.WindowResultList;
|
import org.apache.openjpa.lib.rop.WindowResultList;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||||
|
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FetchGroup;
|
import org.apache.openjpa.meta.FetchGroup;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
@ -58,6 +60,10 @@ public class FetchConfigurationImpl
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(FetchConfigurationImpl.class);
|
(FetchConfigurationImpl.class);
|
||||||
|
|
||||||
|
// Cache the from/to isAssignable invocations
|
||||||
|
private static ConcurrentReferenceHashMap _assignableTypes =
|
||||||
|
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configurable state shared throughout a traversal chain.
|
* Configurable state shared throughout a traversal chain.
|
||||||
*/
|
*/
|
||||||
|
@ -613,11 +619,37 @@ public class FetchConfigurationImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether either of the two types is assignable from the other.
|
* Whether either of the two types is assignable from the other. Optimize
|
||||||
|
* for the repeat calls with similar parameters by caching the from/to
|
||||||
|
* type parameters.
|
||||||
*/
|
*/
|
||||||
private static boolean isAssignable(Class c1, Class c2) {
|
private static boolean isAssignable(Class from, Class to) {
|
||||||
return c1 != null && c2 != null
|
boolean isAssignable;
|
||||||
&& (c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1));
|
|
||||||
|
if (from == null || to == null)
|
||||||
|
return false;
|
||||||
|
ConcurrentReferenceHashMap assignableTo =
|
||||||
|
(ConcurrentReferenceHashMap) _assignableTypes.get(from);
|
||||||
|
|
||||||
|
if (assignableTo != null) { // "to" cache exists...
|
||||||
|
isAssignable = (assignableTo.get(to) != null);
|
||||||
|
if (!isAssignable) { // not in the map yet...
|
||||||
|
isAssignable = from.isAssignableFrom(to);
|
||||||
|
if (isAssignable) {
|
||||||
|
assignableTo.put(to, new Object());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // no "to" cache yet...
|
||||||
|
isAssignable = from.isAssignableFrom(to);
|
||||||
|
if (isAssignable) {
|
||||||
|
assignableTo = new ConcurrentReferenceHashMap(
|
||||||
|
ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||||
|
_assignableTypes.put(from, assignableTo);
|
||||||
|
assignableTo.put(to, new Object());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isAssignable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,6 +17,10 @@ package org.apache.openjpa.util;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.apache.openjpa.lib.util.ReferenceHashSet;
|
||||||
|
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||||
|
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identity class extended by builtin OpenJPA identity objects.
|
* Identity class extended by builtin OpenJPA identity objects.
|
||||||
*
|
*
|
||||||
|
@ -31,6 +35,9 @@ public abstract class OpenJPAId
|
||||||
// type has his based on the least-derived non-object class so that
|
// type has his based on the least-derived non-object class so that
|
||||||
// user-given ids with non-exact types match ids with exact types
|
// user-given ids with non-exact types match ids with exact types
|
||||||
private transient int _typeHash = 0;
|
private transient int _typeHash = 0;
|
||||||
|
// cache the types' generated hashcodes
|
||||||
|
private static ConcurrentReferenceHashMap _typeCache =
|
||||||
|
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||||
|
|
||||||
protected OpenJPAId() {
|
protected OpenJPAId() {
|
||||||
}
|
}
|
||||||
|
@ -82,13 +89,25 @@ public abstract class OpenJPAId
|
||||||
*/
|
*/
|
||||||
protected abstract boolean idEquals(OpenJPAId other);
|
protected abstract boolean idEquals(OpenJPAId other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the hashcode for this Id. Cache the type's generated hashcode
|
||||||
|
* so that it doesn't have to be generated each time.
|
||||||
|
*/
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (_typeHash == 0) {
|
if (_typeHash == 0) {
|
||||||
Class base = type;
|
Integer typeHashInt = (Integer) _typeCache.get(type);
|
||||||
while (base.getSuperclass() != null
|
if (typeHashInt == null) {
|
||||||
&& base.getSuperclass() != Object.class)
|
Class base = type;
|
||||||
base = base.getSuperclass();
|
Class superclass = base.getSuperclass();
|
||||||
_typeHash = base.hashCode();
|
while (superclass != null && superclass != Object.class) {
|
||||||
|
base = base.getSuperclass();
|
||||||
|
superclass = base.getSuperclass();
|
||||||
|
}
|
||||||
|
_typeHash = base.hashCode();
|
||||||
|
_typeCache.put(type, new Integer(_typeHash));
|
||||||
|
} else {
|
||||||
|
_typeHash = typeHashInt.intValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return _typeHash ^ idHash();
|
return _typeHash ^ idHash();
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,8 +94,13 @@ trans-active: The "{0}" transaction property cannot be set during an \
|
||||||
active: This operation cannot be performed while a Transaction is active.
|
active: This operation cannot be performed while a Transaction is active.
|
||||||
closed: The context has been closed. The stack trace at which the \
|
closed: The context has been closed. The stack trace at which the \
|
||||||
context was closed is held in the embedded exception.
|
context was closed is held in the embedded exception.
|
||||||
|
closed-notrace: The context has been closed. The stack trace at which the \
|
||||||
|
context was closed is available if Runtime=TRACE logging is enabled.
|
||||||
closed-factory: The factory has been closed. The stack trace at \
|
closed-factory: The factory has been closed. The stack trace at \
|
||||||
which the factory was closed is held in the embedded exception.
|
which the factory was closed is held in the embedded exception.
|
||||||
|
closed-factory-notrace: The factory has been closed. The stack trace at \
|
||||||
|
which the factory was closed is available if Runtime=TRACE logging is \
|
||||||
|
enabled.
|
||||||
non-trans-read: To perform reads on persistent data outside of a transaction, \
|
non-trans-read: To perform reads on persistent data outside of a transaction, \
|
||||||
the "NontransactionalRead" property must be set on the Transaction.
|
the "NontransactionalRead" property must be set on the Transaction.
|
||||||
non-trans-write: To perform writes on persistent data outside of a \
|
non-trans-write: To perform writes on persistent data outside of a \
|
||||||
|
|
|
@ -17,6 +17,8 @@ package org.apache.openjpa.lib.conf;
|
||||||
|
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||||
|
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object {@link Value}.
|
* An object {@link Value}.
|
||||||
|
@ -28,6 +30,10 @@ public class ObjectValue extends Value {
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(ObjectValue.class);
|
(ObjectValue.class);
|
||||||
|
|
||||||
|
// cache the types' classloader
|
||||||
|
private static ConcurrentReferenceHashMap _classloaderCache =
|
||||||
|
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||||
|
|
||||||
private Object _value = null;
|
private Object _value = null;
|
||||||
|
|
||||||
public ObjectValue(String prop) {
|
public ObjectValue(String prop) {
|
||||||
|
@ -81,10 +87,16 @@ public class ObjectValue extends Value {
|
||||||
* Allow subclasses to instantiate additional plugins. This method does
|
* Allow subclasses to instantiate additional plugins. This method does
|
||||||
* not perform configuration.
|
* not perform configuration.
|
||||||
*/
|
*/
|
||||||
public Object newInstance(String clsName, Class type,
|
public Object newInstance(String clsName, Class type, Configuration conf,
|
||||||
Configuration conf, boolean fatal) {
|
boolean fatal) {
|
||||||
return Configurations.newInstance(clsName, this, conf,
|
ClassLoader cl = (ClassLoader) _classloaderCache.get(type);
|
||||||
type.getClassLoader(), fatal);
|
if (cl == null) {
|
||||||
|
cl = type.getClassLoader();
|
||||||
|
if (cl != null) { // System classloader is returned as null
|
||||||
|
_classloaderCache.put(type, cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Configurations.newInstance(clsName, this, conf, cl, fatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getValueType() {
|
public Class getValueType() {
|
||||||
|
|
Loading…
Reference in New Issue