Dan
please add yourself as author and start putting the "log: danch : useSoft
ref bla bla bla" in the body of the source.
marcf
|-----Original Message-----
|From: [EMAIL PROTECTED]
|[mailto:[EMAIL PROTECTED]]On Behalf Of
|[EMAIL PROTECTED]
|Sent: Monday, June 18, 2001 10:34 AM
|To: [EMAIL PROTECTED]
|Subject: [JBoss-dev] CVS update:
|jboss/src/main/org/jboss/ejb/plugins/jaws/jdbc JDBCCommand.java
|JDBCCommandFactory.java JDBCFindByCommand.java
|JDBCFindEntitiesCommand.java
|
|
| 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/JDBCC
|ommand.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/JDBCC
|ommandFactory.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/JDBCF
|indByCommand.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/JDBCF
|indEntitiesCommand.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
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development