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 {
|
||||
|
||||
private String _tmLoc = "java:/TransactionManager";
|
||||
private static TransactionManager _tm;
|
||||
|
||||
/**
|
||||
* Return the location of the {@link TransactionManager} in JNDI.
|
||||
|
@ -44,13 +45,18 @@ public class JNDIManagedRuntime
|
|||
_tmLoc = name;
|
||||
}
|
||||
|
||||
public TransactionManager getTransactionManager()
|
||||
throws Exception {
|
||||
Context ctx = new InitialContext();
|
||||
try {
|
||||
return (TransactionManager) ctx.lookup(_tmLoc);
|
||||
} finally {
|
||||
ctx.close();
|
||||
/**
|
||||
* Return the cached TransactionManager instance.
|
||||
*/
|
||||
public TransactionManager getTransactionManager() throws Exception {
|
||||
if (_tm == null) {
|
||||
Context ctx = new InitialContext();
|
||||
try {
|
||||
_tm = (TransactionManager) ctx.lookup(_tmLoc);
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _tm;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,8 @@ public abstract class AbstractBrokerFactory
|
|||
// configuration
|
||||
private final OpenJPAConfiguration _conf;
|
||||
private transient boolean _readOnly = false;
|
||||
private transient RuntimeException _closed = null;
|
||||
private transient boolean _closed = false;
|
||||
private transient RuntimeException _closedException = null;
|
||||
private Map _userObjects = null;
|
||||
|
||||
// internal lock: spec forbids synchronization on this object
|
||||
|
@ -267,7 +268,7 @@ public abstract class AbstractBrokerFactory
|
|||
* Returns true if this broker factory is closed.
|
||||
*/
|
||||
public boolean isClosed() {
|
||||
return _closed != null;
|
||||
return _closed;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
@ -297,7 +298,10 @@ public abstract class AbstractBrokerFactory
|
|||
(_conf.getMetaDataRepositoryInstance());
|
||||
|
||||
_conf.close();
|
||||
_closed = new IllegalStateException();
|
||||
_closed = true;
|
||||
Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
|
||||
if (log.isTraceEnabled())
|
||||
_closedException = new IllegalStateException();
|
||||
} finally {
|
||||
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() {
|
||||
if (_closed != null)
|
||||
throw new InvalidStateException(_loc.get("closed-factory")).
|
||||
setCause(_closed);
|
||||
if (_closed) {
|
||||
if (_closedException == null) // TRACE not enabled
|
||||
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.ReferenceHashSet;
|
||||
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.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
|
@ -138,6 +139,9 @@ public class BrokerImpl
|
|||
|
||||
private static final Localizer _loc =
|
||||
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
|
||||
// data cache store manager around the native store manager
|
||||
|
@ -215,7 +219,8 @@ public class BrokerImpl
|
|||
|
||||
// status
|
||||
private int _flags = 0;
|
||||
private RuntimeException _closed = null;
|
||||
private boolean _closed = false;
|
||||
private RuntimeException _closedException = null;
|
||||
|
||||
// event managers
|
||||
private TransactionEventManager _transEventManager = null;
|
||||
|
@ -1096,8 +1101,7 @@ public class BrokerImpl
|
|||
cls));
|
||||
return PCRegistry.newObjectId(cls, (String) val);
|
||||
}
|
||||
|
||||
if (meta.getObjectIdType().isAssignableFrom(val.getClass())) {
|
||||
if (isAssignable(meta.getObjectIdType(), val.getClass())) {
|
||||
if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared())
|
||||
return new ObjectId(cls, 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.
|
||||
*/
|
||||
|
@ -3969,11 +4004,11 @@ public class BrokerImpl
|
|||
///////////
|
||||
|
||||
public boolean isClosed() {
|
||||
return _closed != null;
|
||||
return _closed;
|
||||
}
|
||||
|
||||
public boolean isCloseInvoked() {
|
||||
return _closed != null || (_flags & FLAG_CLOSE_INVOKED) != 0;
|
||||
return _closed || (_flags & FLAG_CLOSE_INVOKED) != 0;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
@ -4055,8 +4090,10 @@ public class BrokerImpl
|
|||
|
||||
_lm.close();
|
||||
_store.close();
|
||||
_closed = new IllegalStateException();
|
||||
_flags = 0;
|
||||
_closed = true;
|
||||
if (_log.isTraceEnabled())
|
||||
_closedException = new IllegalStateException();
|
||||
|
||||
if (err != null)
|
||||
throw err;
|
||||
|
@ -4246,11 +4283,19 @@ public class BrokerImpl
|
|||
/////////
|
||||
// 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() {
|
||||
if (_closed != null)
|
||||
throw new InvalidStateException(_loc.get("closed"), _closed).
|
||||
setFatal(true);
|
||||
if (_closed) {
|
||||
if (_closedException == null) // TRACE not enabled
|
||||
throw new InvalidStateException(_loc.get("closed-notrace"))
|
||||
.setFatal(true);
|
||||
else
|
||||
throw new InvalidStateException(_loc.get("closed"),
|
||||
_closedException).setFatal(true);
|
||||
}
|
||||
}
|
||||
|
||||
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.WindowResultList;
|
||||
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.FetchGroup;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
|
@ -58,6 +60,10 @@ public class FetchConfigurationImpl
|
|||
private static final Localizer _loc = Localizer.forPackage
|
||||
(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.
|
||||
*/
|
||||
|
@ -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) {
|
||||
return c1 != null && c2 != null
|
||||
&& (c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1));
|
||||
private static boolean isAssignable(Class from, Class to) {
|
||||
boolean isAssignable;
|
||||
|
||||
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 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.
|
||||
*
|
||||
|
@ -31,6 +35,9 @@ public abstract class OpenJPAId
|
|||
// 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
|
||||
private transient int _typeHash = 0;
|
||||
// cache the types' generated hashcodes
|
||||
private static ConcurrentReferenceHashMap _typeCache =
|
||||
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||
|
||||
protected OpenJPAId() {
|
||||
}
|
||||
|
@ -82,13 +89,25 @@ public abstract class OpenJPAId
|
|||
*/
|
||||
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() {
|
||||
if (_typeHash == 0) {
|
||||
Class base = type;
|
||||
while (base.getSuperclass() != null
|
||||
&& base.getSuperclass() != Object.class)
|
||||
base = base.getSuperclass();
|
||||
_typeHash = base.hashCode();
|
||||
Integer typeHashInt = (Integer) _typeCache.get(type);
|
||||
if (typeHashInt == null) {
|
||||
Class base = type;
|
||||
Class superclass = base.getSuperclass();
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
closed: The context has been closed. The stack trace at which the \
|
||||
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 \
|
||||
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, \
|
||||
the "NontransactionalRead" property must be set on the Transaction.
|
||||
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.openjpa.lib.util.Localizer;
|
||||
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||
|
||||
/**
|
||||
* An object {@link Value}.
|
||||
|
@ -28,6 +30,10 @@ public class ObjectValue extends Value {
|
|||
private static final Localizer _loc = Localizer.forPackage
|
||||
(ObjectValue.class);
|
||||
|
||||
// cache the types' classloader
|
||||
private static ConcurrentReferenceHashMap _classloaderCache =
|
||||
new ConcurrentReferenceHashMap(ReferenceMap.HARD, ReferenceMap.WEAK);
|
||||
|
||||
private Object _value = null;
|
||||
|
||||
public ObjectValue(String prop) {
|
||||
|
@ -81,10 +87,16 @@ public class ObjectValue extends Value {
|
|||
* Allow subclasses to instantiate additional plugins. This method does
|
||||
* not perform configuration.
|
||||
*/
|
||||
public Object newInstance(String clsName, Class type,
|
||||
Configuration conf, boolean fatal) {
|
||||
return Configurations.newInstance(clsName, this, conf,
|
||||
type.getClassLoader(), fatal);
|
||||
public Object newInstance(String clsName, Class type, Configuration conf,
|
||||
boolean fatal) {
|
||||
ClassLoader cl = (ClassLoader) _classloaderCache.get(type);
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue