User: danch
Date: 01/06/18 07:34:27
Modified: src/main/org/jboss/ejb/plugins/jaws/jdbc JDBCCommand.java
JDBCCommandFactory.java JDBCFindByCommand.java
JDBCFindEntitiesCommand.java
Log:
Use SoftReferences for the preloaded data; also, patch #418196 (creating finders of
nested CMP-fields)
Revision Changes Path
1.33 +2 -2 jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommand.java
Index: JDBCCommand.java
===================================================================
RCS file:
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommand.java,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- JDBCCommand.java 2001/06/06 01:07:40 1.32
+++ JDBCCommand.java 2001/06/18 14:34:27 1.33
@@ -57,7 +57,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Justin Forder</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Dirk Zimmermann</a>
- * @version $Revision: 1.32 $
+ * @version $Revision: 1.33 $
*/
public abstract class JDBCCommand
{
@@ -386,7 +386,7 @@
protected Object getResultObject(ResultSet rs, int idx, Class destination)
throws SQLException{
-log.debug("getting a "+destination.getName()+" from resultset at index "+idx);
+// log.debug("getting a "+destination.getName()+" from resultset at index "+idx);
Object result = null;
Method method = (Method)rsTypes.get(destination.getName());
1.10 +142 -58
jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommandFactory.java
Index: JDBCCommandFactory.java
===================================================================
RCS file:
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommandFactory.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- JDBCCommandFactory.java 2001/06/13 06:52:17 1.9
+++ JDBCCommandFactory.java 2001/06/18 14:34:27 1.10
@@ -8,11 +8,15 @@
package org.jboss.ejb.plugins.jaws.jdbc;
import java.lang.reflect.Method;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.ref.ReferenceQueue;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
+import java.util.WeakHashMap;
import javax.naming.Context;
import javax.naming.InitialContext;
@@ -46,13 +50,25 @@
import org.jboss.logging.Log;
import org.jboss.util.FinderResults;
+import org.jboss.util.TimerTask;
+import org.jboss.util.TimerQueue;
/**
- * JAWSPersistenceManager JDBCCommandFactory
+ * Command factory for the JAWS JDBC layer. This class is primarily responsible
+ * for creating instances of the JDBC implementations for the various JPM
+ * commands so that the JAWSPersistenceManager (actually an persistence store)
+ * can delegate to them in a decoupled manner.
+ * <p>This class also acts as the manager for the read-ahead buffer added in
+ * version 2.3/2.4. In order to manage this buffer, it must register itself
+ * with any transaction that is active when a finder is called so that the
+ * data that was read ahead can be discarded before completion of the
+ * transaction. The read ahead buffer is managed using Soft references, with
+ * a ReferenceQueue being used to tell when the VM has garbage collected an
+ * object so that we can keep the hashtables clean.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Justin Forder</a>
* @author <a href="[EMAIL PROTECTED]">danch (Dan Christopherson</a>
- * @version $Revision: 1.9 $
+ * @version $Revision: 1.10 $
*/
public class JDBCCommandFactory implements JPMCommandFactory
{
@@ -63,7 +79,15 @@
private JawsEntityMetaData metadata;
private Log log;
private boolean debug = false;
+
+ /** Timer queue used to time polls on the preloadRefQueue on all JAWS
+ * handled entities
+ */
+ private static TimerQueue softRefHandler;
+ /** Timer queue used to get references to preload data who've been GC'ed */
+ private ReferenceQueue preloadRefQueue = new ReferenceQueue();
+
/** a map of data preloaded within some transaction for some entity. This map
* is keyed by Transaction and the data are hashmaps with key = entityKey and
* data = Object[] containing the entity data.
@@ -81,7 +105,13 @@
// These support singletons (within the scope of this factory)
private JDBCBeanExistsCommand beanExistsCommand;
private JPMFindEntitiesCommand findEntitiesCommand;
-
+
+ //static initializer to kick off our softRefhandler
+ static {
+ softRefHandler = new TimerQueue("JAWS Preload reference handler");
+ softRefHandler.start();
+ }
+
// Constructors --------------------------------------------------
public JDBCCommandFactory(EntityContainer container,
@@ -93,24 +123,26 @@
this.javaCtx = (Context)new InitialContext().lookup("java:comp/env");
- String ejbName = container.getBeanMetaData().getEjbName();
- ApplicationMetaData amd =
container.getBeanMetaData().getApplicationMetaData();
- JawsApplicationMetaData jamd =
(JawsApplicationMetaData)amd.getPluginData("JAWS");
-
- if (jamd == null) {
- // we are the first cmp entity to need jaws. Load jaws.xml for the whole
application
- JawsXmlFileLoader jfl = new JawsXmlFileLoader(amd,
container.getClassLoader(), container.getLocalClassLoader(), log);
- jamd = jfl.load();
- amd.addPluginData("JAWS", jamd);
- }
- debug = jamd.getDebug();
-
- metadata = jamd.getBeanByEjbName(ejbName);
- if (metadata == null) {
- throw new DeploymentException("No metadata found for bean " +
ejbName);
- }
+ String ejbName = container.getBeanMetaData().getEjbName();
+ ApplicationMetaData amd =
container.getBeanMetaData().getApplicationMetaData();
+ JawsApplicationMetaData jamd =
(JawsApplicationMetaData)amd.getPluginData("JAWS");
+
+ if (jamd == null) {
+ // we are the first cmp entity to need jaws. Load jaws.xml for the whole
application
+ JawsXmlFileLoader jfl = new JawsXmlFileLoader(amd,
container.getClassLoader(), container.getLocalClassLoader(), log);
+ jamd = jfl.load();
+ amd.addPluginData("JAWS", jamd);
+ }
+ debug = jamd.getDebug();
+
+ metadata = jamd.getBeanByEjbName(ejbName);
+ if (metadata == null) {
+ throw new DeploymentException("No metadata found for bean " + ejbName);
+ }
+
+ tm = (TransactionManager) container.getTransactionManager();
- tm = (TransactionManager) container.getTransactionManager();
+ softRefHandler.schedule(new PreloadRefQueueHandlerTask(), 50);
}
// Public --------------------------------------------------------
@@ -262,10 +294,10 @@
try {
trans = tm.getTransaction();
} catch (javax.transaction.SystemException sysE) {
- log.warning("System exception getting transaction for preload - can't get
preloaded data for "+entityKey);
+ log.warning("System exception getting transaction for preload - can't
preload data for "+entityKey);
return;
}
-//log.debug("PRELOAD: adding preload for "+entityKey+" in transaction "+(trans !=
null ? trans.toString() : "NONE"));
+//log.debug("PRELOAD: adding preload for "+entityKey+" in transaction "+(trans !=
null ? trans.toString() : "NONE")+" entityData="+entityData);
if (trans != null) {
synchronized (preloadedData) {
@@ -283,11 +315,13 @@
entitiesInTransaction = new HashMap();
preloadedData.put(trans, entitiesInTransaction);
}
- entitiesInTransaction.put(entityKey, entityData);
+ PreloadData preloadData = new PreloadData(trans, entityKey, entityData,
preloadRefQueue);
+ entitiesInTransaction.put(entityKey, preloadData);
}
} else {
synchronized (nonTransactionalPreloadData) {
- nonTransactionalPreloadData.put(entityKey, entityData);
+ PreloadData preloadData = new PreloadData(null, entityKey, entityData,
preloadRefQueue);
+ nonTransactionalPreloadData.put(entityKey, preloadData);
}
}
}
@@ -306,19 +340,36 @@
}
Object[] result = null;
+ PreloadData preloadData = null;
if (trans != null) {
- synchronized (preloadedData) {
- Map entitiesInTransaction = (Map)preloadedData.get(trans);
- if (entitiesInTransaction != null)
- result = (Object[])entitiesInTransaction.get(entityKey);
- //remove it now?
+ Map entitiesInTransaction = null;
+ // Do we really need this to be syncrhonized? What is the effect of
+ // another thread trying to modify this map? It won't be to remove
+ // our transaction (we're in it here!, trying to call a business
+ // method), and who cares if another is added/removed?
+// synchronized (preloadedData) {
+ entitiesInTransaction = (Map)preloadedData.get(trans);
+// }
+ if (entitiesInTransaction != null) {
+ synchronized (entitiesInTransaction) {
+ preloadData = (PreloadData)entitiesInTransaction.get(entityKey);
+ entitiesInTransaction.remove(entityKey);
+ }
}
} else {
synchronized (nonTransactionalPreloadData) {
- result = (Object[])nonTransactionalPreloadData.get(entityKey);
+ preloadData = (PreloadData)nonTransactionalPreloadData.get(entityKey);
+ nonTransactionalPreloadData.remove(entityKey);
}
}
-//log.debug("PRELOAD: returning "+result+" as preload for "+entityKey);
+ if (preloadData != null) {
+ result = preloadData.getData();
+ } /*else {
+ log.debug("PRELOAD: preloadData == null for "+entityKey);
+ }
+if (result == null)
+ log.debug("PRELOAD: returning null as preload for "+entityKey);
+ */
return result;
}
@@ -333,38 +384,71 @@
// Private -------------------------------------------------------
- /** an inner class used to key the FinderResults by their finder method and
- * the transaction they're invoked within
+
+ /** Inner class that handles our reference queue. I didn't think this would
+ * be neccessary, but for some reason the VM won't call an override of
+ * Reference.clear()
+ */
+ private class PreloadRefQueueHandlerTask extends TimerTask {
+ public void execute() throws Exception {
+ PreloadData preloadData = (PreloadData)preloadRefQueue.poll();
+ int handled = 0;
+ while (preloadData != null && handled < 10) {
+ log.debug("PRELOAD: clearing "+preloadData.getKey());
+ if (preloadData.getTransaction() != null) {
+ Map entitiesInTransaction = null;
+ // Do we really need this to be syncrhonized? What is the effect of
+ // another thread trying to modify this map? It won't be to remove
+ // our transaction (we're in it here!, trying to call a business
+ // method), and who cares if another is added/removed?
+ // synchronized (preloadedData) {
+ entitiesInTransaction =
(Map)preloadedData.get(preloadData.getTransaction());
+ // }
+ if (entitiesInTransaction != null) {
+ synchronized (entitiesInTransaction) {
+ entitiesInTransaction.remove(preloadData.getKey());
+ }
+ }
+ } else {
+ synchronized (nonTransactionalPreloadData) {
+ nonTransactionalPreloadData.remove(preloadData.getKey());
+ }
+ }
+ preloadData.empty();
+ handled++;
+
+ preloadData = (PreloadData)preloadRefQueue.poll();
+ }
+ }
+ }
+ /** Inner class used in the preload Data hashmaps so that we can wrap a
+ * SoftReference around the data and still have enough information to remove
+ * the reference from the appropriate hashMap.
*/
- private static class PreloadDataKey {
- private Object entityKey;
- private Transaction transaction;
-
- private int hashCode;
+ private class PreloadData extends SoftReference {
+ private Object key;
+ private Transaction trans;
- public PreloadDataKey(Object entityKey, Transaction transaction) {
- this.entityKey = entityKey;
- this.transaction = transaction;
-
- //accumulate the hashcode.
- /** @todo investigate ways of combining these that will give the least
collisions */
- this.hashCode = entityKey.hashCode();
- if (transaction != null)
- this.hashCode += transaction.hashCode();
+ PreloadData(Transaction trans, Object key, Object[] data, ReferenceQueue
queue) {
+ super(data, queue);
+ this.trans = trans;
+ this.key = key;
}
- public int hashCode() {
- return hashCode;
+ Transaction getTransaction() {
+ return trans;
}
- public boolean equals(Object o) {
- if (o instanceof PreloadDataKey) {
- PreloadDataKey other = (PreloadDataKey)o;
- return (other.entityKey.equals(this.entityKey)) &&
- ( (other.transaction == null && this.transaction == null) ||
- ( (other.transaction != null && this.transaction != null) &&
- (other.transaction.equals(this.transaction)) ) );
- }
- return false;
+ Object getKey() {
+ return key;
+ }
+ Object[] getData() {
+ return (Object[])get();
+ }
+
+ /** Named empty to not collide with superclass clear */
+ public void empty() {
+ key = null;
+ trans = null;
}
}
1.10 +5 -2
jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCFindByCommand.java
Index: JDBCFindByCommand.java
===================================================================
RCS file:
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCFindByCommand.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- JDBCFindByCommand.java 2001/06/13 06:52:17 1.9
+++ JDBCFindByCommand.java 2001/06/18 14:34:27 1.10
@@ -27,7 +27,8 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Joe Shevland</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Justin Forder</a>
* @author <a href="mailto:[EMAIL PROTECTED]">danch (Dan Christopherson)</a>
- * @version $Revision: 1.9 $
+ * @author <a href="mailto:[EMAIL PROTECTED]">Torben J�ger</a>
+ * @version $Revision: 1.10 $
*/
public class JDBCFindByCommand extends JDBCFinderCommand
{
@@ -55,7 +56,9 @@
{
CMPFieldMetaData fi = (CMPFieldMetaData)iter.next();
- if (cmpFieldName.equals(fi.getName().toLowerCase()))
+ String lastComponentOfName =
+ CMPFieldMetaData.getLastComponent(fi.getName()).toLowerCase();
+ if (cmpFieldName.equals(lastComponentOfName))
{
cmpField = fi;
}
1.10 +3 -2
jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCFindEntitiesCommand.java
Index: JDBCFindEntitiesCommand.java
===================================================================
RCS file:
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCFindEntitiesCommand.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- JDBCFindEntitiesCommand.java 2001/05/27 00:49:15 1.9
+++ JDBCFindEntitiesCommand.java 2001/06/18 14:34:27 1.10
@@ -33,7 +33,7 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Joe Shevland</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Justin Forder</a>
- * @version $Revision: 1.9 $
+ * @version $Revision: 1.10 $
*/
public class JDBCFindEntitiesCommand implements JPMFindEntitiesCommand
{
@@ -74,7 +74,8 @@
}
}
} catch (Exception e) {
- // for some reason, this failed; try to use defined or automatic
instead
+ // for some reason, this failed; try to use defined or automatic instead
+ factory.getLog().warning("Error initializing custom finder
"+e.getMessage());
}
// Make commands for the defined finders
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development