You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2005/12/31 19:51:59 UTC

cvs commit: db-ojb/src/java/org/apache/ojb/odmg ImplementationImpl.java NamedRootsMap.java ObjectEnvelope.java ObjectEnvelopeOrdering.java ObjectEnvelopeTable.java TransactionImpl.java

arminw      2005/12/31 10:51:59

  Modified:    src/java/org/apache/ojb/odmg/collections Tag:
                        OJB_1_0_RELEASE DListEntry.java DListImpl.java
                        DListIterator.java DMapImpl.java DSetImpl.java
               src/java/org/apache/ojb/odmg/oql Tag: OJB_1_0_RELEASE
                        OQLQueryImpl.java
               src/java/org/apache/ojb/odmg Tag: OJB_1_0_RELEASE
                        ImplementationImpl.java NamedRootsMap.java
                        ObjectEnvelope.java ObjectEnvelopeOrdering.java
                        ObjectEnvelopeTable.java TransactionImpl.java
  Log:
  performance improvement, code cleanup. Now the lockAndRegister method handle circular references self-dependent instead of require a list of all performed objects as method argument
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.25.2.5  +2 -2      db-ojb/src/java/org/apache/ojb/odmg/collections/DListEntry.java
  
  Index: DListEntry.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/collections/DListEntry.java,v
  retrieving revision 1.25.2.4
  retrieving revision 1.25.2.5
  diff -u -r1.25.2.4 -r1.25.2.5
  --- DListEntry.java	21 Dec 2005 22:29:50 -0000	1.25.2.4
  +++ DListEntry.java	31 Dec 2005 18:51:58 -0000	1.25.2.5
  @@ -149,7 +149,7 @@
                   if(realSubject != null)
                   {
                       RuntimeObject rt = new RuntimeObject(realSubject, tx, false);
  -                    tx.lockAndRegister(rt, Transaction.READ, tx.getRegistrationList());
  +                    tx.lockAndRegister(rt, Transaction.READ);
                   }
               }
               else
  
  
  
  1.27.2.6  +9 -12     db-ojb/src/java/org/apache/ojb/odmg/collections/DListImpl.java
  
  Index: DListImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/collections/DListImpl.java,v
  retrieving revision 1.27.2.5
  retrieving revision 1.27.2.6
  diff -u -r1.27.2.5 -r1.27.2.6
  --- DListImpl.java	21 Dec 2005 22:29:50 -0000	1.27.2.5
  +++ DListImpl.java	31 Dec 2005 18:51:58 -0000	1.27.2.6
  @@ -167,14 +167,13 @@
           if (checkForOpenTransaction(tx))
           {
               RuntimeObject rt = new RuntimeObject(this, tx);
  -            List regList = tx.getRegistrationList();
  -            tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
  +            tx.lockAndRegister(rt, Transaction.WRITE, false);
   
               rt = new RuntimeObject(element, tx);
  -            tx.lockAndRegister(rt, Transaction.READ, regList);
  +            tx.lockAndRegister(rt, Transaction.READ);
   
               rt = new RuntimeObject(entry, tx, true);
  -            tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
  +            tx.lockAndRegister(rt, Transaction.WRITE, false);
           }
   
           // changing the position markers of entries:
  @@ -185,6 +184,7 @@
           }
           catch (Exception ignored)
           {
  +            // ignore
           }
           for (int i = offset; i < elements.size(); i++)
           {
  @@ -228,6 +228,7 @@
           }
           catch (Exception ignored)
           {
  +            // ignore
           }
           for (int i = offset; i < elements.size(); i++)
           {
  @@ -266,10 +267,7 @@
       public boolean existsElement(String predicate) throws org.odmg.QueryInvalidException
       {
           DList results = (DList) this.query(predicate);
  -        if (results == null || results.size() == 0)
  -            return false;
  -        else
  -            return true;
  +        return !(results == null || results.size() == 0);
       }
   
       /**
  @@ -390,8 +388,7 @@
           // we ll have to compute the most general extent class here !!!
           DListEntry entry = (DListEntry) elements.get(0);
           Class elementsClass = entry.getRealSubject().getClass();
  -        Class extentClass = brokerForClass.getTopLevelClass(elementsClass);
  -        return extentClass;
  +        return brokerForClass.getTopLevelClass(elementsClass);
       }
   
       /**
  @@ -422,7 +419,7 @@
               // join selection of elements with predicate criteria:
               allElementsCriteria.addAndCriteria(pCrit);
   
  -            Class clazz = null;
  +            Class clazz;
               try
               {
                   clazz = this.getElementsExtentClass(broker);
  
  
  
  1.8.2.5   +2 -2      db-ojb/src/java/org/apache/ojb/odmg/collections/DListIterator.java
  
  Index: DListIterator.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/collections/DListIterator.java,v
  retrieving revision 1.8.2.4
  retrieving revision 1.8.2.5
  diff -u -r1.8.2.4 -r1.8.2.5
  --- DListIterator.java	21 Dec 2005 22:29:50 -0000	1.8.2.4
  +++ DListIterator.java	31 Dec 2005 18:51:58 -0000	1.8.2.5
  @@ -63,7 +63,7 @@
           if (tx != null)
           {
               RuntimeObject rt = new RuntimeObject(entry, tx, true);
  -            tx.lockAndRegister(rt, Transaction.WRITE, false, tx.getRegistrationList());
  +            tx.lockAndRegister(rt, Transaction.WRITE, false);
           }
       }
   
  
  
  
  1.21.2.6  +6 -8      db-ojb/src/java/org/apache/ojb/odmg/collections/DMapImpl.java
  
  Index: DMapImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/collections/DMapImpl.java,v
  retrieving revision 1.21.2.5
  retrieving revision 1.21.2.6
  diff -u -r1.21.2.5 -r1.21.2.6
  --- DMapImpl.java	21 Dec 2005 22:29:50 -0000	1.21.2.5
  +++ DMapImpl.java	31 Dec 2005 18:51:58 -0000	1.21.2.6
  @@ -19,7 +19,6 @@
   import java.util.AbstractMap;
   import java.util.Iterator;
   import java.util.Set;
  -import java.util.List;
   
   import org.apache.ojb.broker.PBKey;
   import org.apache.ojb.broker.PersistenceBroker;
  @@ -28,10 +27,10 @@
   import org.apache.ojb.broker.util.collections.ManageableHashSet;
   import org.apache.ojb.broker.util.logging.Logger;
   import org.apache.ojb.broker.util.logging.LoggerFactory;
  +import org.apache.ojb.odmg.RuntimeObject;
   import org.apache.ojb.odmg.TransactionExt;
   import org.apache.ojb.odmg.TransactionImpl;
   import org.apache.ojb.odmg.TxManagerFactory;
  -import org.apache.ojb.odmg.RuntimeObject;
   import org.odmg.DMap;
   import org.odmg.Transaction;
   
  @@ -148,18 +147,17 @@
               TransactionImpl tx = getTransaction();
               if ((tx != null) && (tx.isOpen()))
               {
  -                List regList = tx.getRegistrationList();
                   RuntimeObject rt = new RuntimeObject(this, tx);
  -                tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
  +                tx.lockAndRegister(rt, Transaction.WRITE, false);
   
                   rt = new RuntimeObject(key, tx);
  -                tx.lockAndRegister(rt, Transaction.READ, regList);
  +                tx.lockAndRegister(rt, Transaction.READ);
   
                   rt = new RuntimeObject(value, tx);
  -                tx.lockAndRegister(rt, Transaction.READ, regList);
  +                tx.lockAndRegister(rt, Transaction.READ);
   
                   rt = new RuntimeObject(entry, tx, true);
  -                tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
  +                tx.lockAndRegister(rt, Transaction.WRITE, false);
               }
               return null;
           }
  
  
  
  1.21.2.6  +5 -10     db-ojb/src/java/org/apache/ojb/odmg/collections/DSetImpl.java
  
  Index: DSetImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/collections/DSetImpl.java,v
  retrieving revision 1.21.2.5
  retrieving revision 1.21.2.6
  diff -u -r1.21.2.5 -r1.21.2.6
  --- DSetImpl.java	21 Dec 2005 22:29:50 -0000	1.21.2.5
  +++ DSetImpl.java	31 Dec 2005 18:51:58 -0000	1.21.2.6
  @@ -155,15 +155,14 @@
               TransactionImpl tx = getTransaction();
               if ((tx != null) && (tx.isOpen()))
               {
  -                List regList = tx.getRegistrationList();
                   RuntimeObject rt = new RuntimeObject(this, tx);
  -                tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
  +                tx.lockAndRegister(rt, Transaction.WRITE, false);
   
                   rt = new RuntimeObject(o, tx);
  -                tx.lockAndRegister(rt, Transaction.READ, regList);
  +                tx.lockAndRegister(rt, Transaction.READ);
   
                   rt = new RuntimeObject(entry, tx, true);
  -                tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
  +                tx.lockAndRegister(rt, Transaction.WRITE, false);
               }
               return true;
           }
  @@ -206,10 +205,7 @@
       public boolean existsElement(String predicate) throws org.odmg.QueryInvalidException
       {
           DList results = (DList) this.query(predicate);
  -        if (results == null || results.size() == 0)
  -            return false;
  -        else
  -            return true;
  +        return !(results == null || results.size() == 0);
       }
   
       public List getElements()
  @@ -370,8 +366,7 @@
           // we ll have to compute the most general extent class here !!!
           DListEntry entry = (DListEntry) elements.get(0);
           Class elementsClass = entry.getRealSubject().getClass();
  -        Class extentClass = broker.getTopLevelClass(elementsClass);
  -        return extentClass;
  +        return broker.getTopLevelClass(elementsClass);
       }
   
   
  
  
  
  No                   revision
  No                   revision
  1.18.2.6  +8 -19     db-ojb/src/java/org/apache/ojb/odmg/oql/OQLQueryImpl.java
  
  Index: OQLQueryImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/oql/OQLQueryImpl.java,v
  retrieving revision 1.18.2.5
  retrieving revision 1.18.2.6
  diff -u -r1.18.2.5 -r1.18.2.6
  --- OQLQueryImpl.java	21 Dec 2005 22:29:53 -0000	1.18.2.5
  +++ OQLQueryImpl.java	31 Dec 2005 18:51:58 -0000	1.18.2.6
  @@ -20,7 +20,6 @@
   import java.util.Iterator;
   import java.util.ListIterator;
   import java.util.Vector;
  -import java.util.List;
   
   import antlr.RecognitionException;
   import antlr.TokenStreamException;
  @@ -256,9 +255,8 @@
               }
               else
               {
  -                Iterator iter = null;
                   result = new ManageableArrayList();
  -                iter = broker.getReportQueryIteratorByQuery(query);
  +                Iterator iter = broker.getReportQueryIteratorByQuery(query);
                   try
                   {
                       while (iter.hasNext())
  @@ -320,20 +318,12 @@
           {
               // read-lock all resulting objects to the current transaction
               Iterator iter = result.ojbIterator();
  -            Object toBeLocked = null;
  -            try
  +            Object toBeLocked;
  +            while (iter.hasNext())
               {
  -                List regList = tx.getRegistrationList();
  -                while (iter.hasNext())
  -                {
  -                    toBeLocked = iter.next();
  -                    RuntimeObject rt = new RuntimeObject(toBeLocked, tx, false);
  -                    tx.lockAndRegister(rt, Transaction.READ, true, regList);
  -                }
  -            }
  -            finally
  -            {
  -                tx.clearRegistrationList();
  +                toBeLocked = iter.next();
  +                RuntimeObject rt = new RuntimeObject(toBeLocked, tx, false);
  +                tx.lockAndRegister(rt, Transaction.READ, true);
               }
           }
       }
  @@ -341,8 +331,7 @@
   
       protected OdmgConfiguration getConfiguration()
       {
  -        OdmgConfiguration config = (OdmgConfiguration) PersistenceBrokerFactory.getConfigurator().getConfigurationFor(null);
  -        return config;
  +        return (OdmgConfiguration) PersistenceBrokerFactory.getConfigurator().getConfigurationFor(null);
       }
   
   
  
  
  
  No                   revision
  No                   revision
  1.1.2.14  +24 -24    db-ojb/src/java/org/apache/ojb/odmg/ImplementationImpl.java
  
  Index: ImplementationImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/ImplementationImpl.java,v
  retrieving revision 1.1.2.13
  retrieving revision 1.1.2.14
  diff -u -r1.1.2.13 -r1.1.2.14
  --- ImplementationImpl.java	31 Dec 2005 18:28:32 -0000	1.1.2.13
  +++ ImplementationImpl.java	31 Dec 2005 18:51:58 -0000	1.1.2.14
  @@ -15,7 +15,6 @@
    * limitations under the License.
    */
   
  -import org.apache.commons.lang.SerializationUtils;
   import org.apache.commons.lang.builder.ToStringBuilder;
   import org.apache.commons.lang.builder.ToStringStyle;
   import org.apache.ojb.broker.Identity;
  @@ -41,8 +40,8 @@
   import org.odmg.DatabaseClosedException;
   import org.odmg.Implementation;
   import org.odmg.ODMGRuntimeException;
  -import org.odmg.Transaction;
   import org.odmg.OQLQuery;
  +import org.odmg.Transaction;
   
   
   /**
  @@ -279,37 +278,38 @@
        */
       public String getObjectId(Object obj)
       {
  -        Identity oid = null;
  -        PersistenceBroker broker = null;
  +        Identity oid;
   
  -        try
  +        if (getCurrentDatabase() != null)
           {
  -            if (getCurrentDatabase() != null)
  +            /**
  +             * is there an open database we are calling getObjectId against? if yes, use it
  +             */
  +            TransactionImpl tx = ojbTxManager.getTransaction();
  +            if(tx == null || !tx.isOpen())
               {
  -                /**
  -                 * is there an open database we are calling getObjectId against? if yes, use it
  -                 */
  -                broker = PersistenceBrokerFactory.createPersistenceBroker(getCurrentDatabase().getPBKey());
  +                PersistenceBroker broker = PersistenceBrokerFactory.createPersistenceBroker(getCurrentDatabase().getPBKey());
  +                oid = broker.serviceIdentity().buildIdentity(obj);
  +                broker.close();
               }
               else
               {
  -                log.warn("Can't find open database, try to use the default configuration");
  -                /**
  -                 * otherwise, use default.
  -                 */
  -                broker = PersistenceBrokerFactory.defaultPersistenceBroker();
  +                PersistenceBroker broker = tx.getBrokerInternal();
  +                oid = broker.serviceIdentity().buildIdentity(obj);
  +                // broker will be closed by tx
               }
  -
  -            oid = broker.serviceIdentity().buildIdentity(obj);
           }
  -        finally
  +        else
           {
  -            if(broker != null)
  -            {
  -                broker.close();
  -            }
  +            log.warn("Can't find open database, try to use the default configuration");
  +            /**
  +             * otherwise, use default.
  +             */
  +            PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker();
  +            oid = broker.serviceIdentity().buildIdentity(obj);
  +            broker.close();
           }
  -        return new String(SerializationUtils.serialize(oid));
  +        return oid.toString();
       }
   
       /**
  
  
  
  1.12.2.6  +13 -16    db-ojb/src/java/org/apache/ojb/odmg/NamedRootsMap.java
  
  Index: NamedRootsMap.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/NamedRootsMap.java,v
  retrieving revision 1.12.2.5
  retrieving revision 1.12.2.6
  diff -u -r1.12.2.5 -r1.12.2.6
  --- NamedRootsMap.java	21 Dec 2005 22:29:21 -0000	1.12.2.5
  +++ NamedRootsMap.java	31 Dec 2005 18:51:58 -0000	1.12.2.6
  @@ -41,14 +41,13 @@
    * therefore the NamedRootsMap underlies the same transaction management
    * as all other persistent objects
    *
  - * @author Thomas Mahler
    * @version $Id$
    */
   public class NamedRootsMap
   {
       private Logger log = LoggerFactory.getLogger(NamedRootsMap.class);
  -    private TransactionImpl tx;
  -    private HashMap tempBindings;
  +    private final TransactionImpl tx;
  +    private final HashMap tempBindings;
       private Map deletionMap;
       private Map insertMap;
   
  @@ -83,9 +82,7 @@
        */
       public void performDeletion()
       {
  -        if(deletionMap == null)
  -            return;
  -        else
  +        if(deletionMap != null)
           {
               PersistenceBroker broker = tx.getBroker();
               Iterator it = deletionMap.values().iterator();
  @@ -103,9 +100,7 @@
        */
       public void performInsert()
       {
  -        if(insertMap == null)
  -            return;
  -        else
  +        if(insertMap != null)
           {
               PersistenceBroker broker = tx.getBroker();
               Iterator it = insertMap.values().iterator();
  @@ -118,10 +113,11 @@
           }
       }
   
  -    public void afterWriteCleanup()
  +    public void cleanup()
       {
  -        if(deletionMap != null) deletionMap.clear();
  -        if(insertMap != null) insertMap.clear();
  +        if(deletionMap != null && deletionMap.size() > 0) deletionMap.clear();
  +        if(insertMap != null && insertMap.size() > 0) insertMap.clear();
  +        if(tempBindings.size() > 0) insertMap.clear();
       }
   
       private void localBind(String key, NamedEntry entry) throws ObjectNameNotUniqueException
  @@ -183,7 +179,7 @@
                   result = tx.getBroker().getObjectByIdentity(objectIdentity);
                   // lock the persistance capable object
                   RuntimeObject rt = new RuntimeObject(result, objectIdentity, tx, false);
  -                tx.lockAndRegister(rt, Transaction.READ, tx.getRegistrationList());
  +                tx.lockAndRegister(rt, Transaction.READ);
               }
               else
               {
  @@ -214,8 +210,9 @@
           {
               cld = broker.getClassDescriptor(ProxyHelper.getRealClass(object));
           }
  -        catch(PersistenceBrokerException e)
  +        catch(PersistenceBrokerException ignore)
           {
  +            // ignore
           }
   
           // if null a non-persistent capable object was specified
  @@ -237,7 +234,7 @@
               // else persist the specified named object
               if(!rt.isNew())
               {
  -                tx.lockAndRegister(rt, Transaction.READ, tx.getRegistrationList());
  +                tx.lockAndRegister(rt, Transaction.READ);
               }
               else
               {
  
  
  
  1.32.2.22 +68 -44    db-ojb/src/java/org/apache/ojb/odmg/ObjectEnvelope.java
  
  Index: ObjectEnvelope.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/ObjectEnvelope.java,v
  retrieving revision 1.32.2.21
  retrieving revision 1.32.2.22
  diff -u -r1.32.2.21 -r1.32.2.22
  --- ObjectEnvelope.java	21 Dec 2005 22:29:21 -0000	1.32.2.21
  +++ ObjectEnvelope.java	31 Dec 2005 18:51:58 -0000	1.32.2.22
  @@ -14,12 +14,6 @@
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
  -/**
  - *
  - * @author <a href="mailto:thma@apache.org">Thomas Mahler</a>
  - * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
  - *
  - */
   
   import java.util.HashMap;
   import java.util.Iterator;
  @@ -73,6 +67,8 @@
       private Identity oid;
       private Boolean hasChanged;
       private boolean writeLocked;
  +    private boolean markedForCascadingInsert;
  +    private boolean markedForCascadingDelete;
   
       /**
        * myObj holds the object we are wrapping.
  @@ -94,7 +90,7 @@
       /**
        * Create a wrapper by providing an Object.
        */
  -    public ObjectEnvelope(ObjectEnvelopeTable buffer, Identity oid, Object obj, boolean isNewObject)
  +    ObjectEnvelope(ObjectEnvelopeTable buffer, Identity oid, Object obj, boolean isNewObject)
       {
           this.linkEntryList = new ArrayList();
           this.buffer = buffer;
  @@ -102,12 +98,7 @@
           // TODO: do we really need to materialize??
           myObj = ProxyHelper.getRealObject(obj);
           prepareInitialState(isNewObject);
  -        /*
  -        TODO: is it possible to improve this? Take care that "new"
  -        objects should support "persistence by reachability" too
  -        (detection of new/persistent reference objects after maon object lock)
  -        */
  -        beforeImage = buildObjectImage(getBroker());
  +        beforeImage = buildObjectImage(getBroker(), isNewObject);
       }
   
       public PersistenceBrokerInternal getBroker()
  @@ -125,7 +116,7 @@
           return buffer;
       }
   
  -    public Map getBeforeImage()
  +    private Map getBeforeImage()
       {
           if(beforeImage == null)
           {
  @@ -134,11 +125,11 @@
           return beforeImage;
       }
   
  -    public Map getCurrentImage()
  +    private Map getCurrentImage()
       {
           if(currentImage == null)
           {
  -            currentImage = buildObjectImage(getBroker());
  +            currentImage = buildObjectImage(getBroker(), needsInsert());
           }
           return currentImage;
       }
  @@ -179,10 +170,13 @@
           }
       }
   
  -    private void refreshObjectImage(boolean wasInsert)
  +    private void refreshObjectImage(boolean wasNewObject)
       {
           try
           {
  +            markedForCascadingInsert = false;
  +            markedForCascadingDelete = false;
  +            
               // if an image already exists we
               // replace the Identity too, maybe a temporary
               // used PK value was replaced by the real one,
  @@ -199,18 +193,19 @@
               {
                   if(beforeImage == null)
                   {
  -                    beforeImage = buildObjectImage(getBroker());
  +                    beforeImage = buildObjectImage(getBroker(), wasNewObject);
                   }
               }
               currentImage = null;
               hasChanged = null;
  -            if(wasInsert)
  +            if(wasNewObject)
               {
                   /*
                   on insert we have to replace the PK fields and the version fields, because
                   they populated after the object was written to DB, thus replace all field image values
                   */
  -                refreshPKFields();
  +                // refreshPKFields();
  +                buildImageForFields(beforeImage, getClassDescriptor());
               }
               // TODO: How to handle version fields incremented by the DB?
               // always refresh the version fields, because these fields will change when written to DB
  @@ -226,15 +221,15 @@
           }
       }
   
  -    private void refreshPKFields()
  -    {
  -        FieldDescriptor[] flds = getClassDescriptor().getPkFields();
  -        for(int i = 0; i < flds.length; i++)
  -        {
  -            FieldDescriptor fld = flds[i];
  -            addFieldImage(beforeImage, fld);
  -        }
  -    }
  +//    private void refreshPKFields()
  +//    {
  +//        FieldDescriptor[] flds = getClassDescriptor().getPkFields();
  +//        for(int i = 0; i < flds.length; i++)
  +//        {
  +//            FieldDescriptor fld = flds[i];
  +//            addFieldImage(beforeImage, fld);
  +//        }
  +//    }
   
       private void refreshLockingFields()
       {
  @@ -358,13 +353,18 @@
        */
       private Map buildObjectImage(PersistenceBroker broker) throws PersistenceBrokerException
       {
  +        return buildObjectImage(broker, false);
  +    }
  +
  +    private Map buildObjectImage(PersistenceBroker broker, boolean isNew) throws PersistenceBrokerException
  +    {
           Map imageMap = new HashMap();
           ClassDescriptor cld = broker.getClassDescriptor(getObject().getClass());
           //System.out.println("++++ build image: " + getObject());
           // register 1:1 references in image
           buildImageForSingleReferences(imageMap, cld);
  -        // put object values to image map
  -        buildImageForFields(imageMap, cld);
  +        // put object values to image map, skip this for new objects
  +        if(!isNew) buildImageForFields(imageMap, cld);
           // register 1:n and m:n references in image
           buildImageForCollectionReferences(imageMap, cld);
           return imageMap;
  @@ -503,7 +503,7 @@
               initialState = StateOldClean.getInstance();
           }
           // remember it:
  -        modificationState = initialState;
  +        this.modificationState = initialState;
       }
   
       /**
  @@ -526,18 +526,18 @@
        */
       public void setModificationState(ModificationState newModificationState)
       {
  -        if(newModificationState != modificationState)
  +        if(newModificationState != this.modificationState)
           {
               if(log.isDebugEnabled())
               {
                   log.debug("object state transition for object " + this.oid + " ("
  -                        + modificationState + " --> " + newModificationState + ")");
  +                        + this.modificationState + " --> " + newModificationState + ")");
   //                try{throw new Exception();}catch(Exception e)
   //                {
   //                e.printStackTrace();
   //                }
               }
  -            modificationState = newModificationState;
  +            this.modificationState = newModificationState;
           }
       }
   
  @@ -549,7 +549,7 @@
       {
           ToStringBuilder buf = new ToStringBuilder(this);
           buf.append("Identity", oid)
  -            .append("ModificationState", modificationState.toString());
  +            .append("ModificationState", (modificationState != null ? modificationState.toString() : "invalid"));
           return buf.toString();
       }
   
  @@ -658,16 +658,36 @@
           getBroker().removeFromCache(getIdentity());
       }
   
  -    public boolean isWriteLocked()
  +    boolean isWriteLocked()
       {
           return writeLocked;
       }
   
  -    public void setWriteLocked(boolean writeLocked)
  +    void setWriteLocked(boolean writeLocked)
       {
           this.writeLocked = writeLocked;
       }
   
  +    boolean isMarkedForCascadingInsert()
  +    {
  +        return markedForCascadingInsert;
  +    }
  +
  +    void markForCascadingInsert()
  +    {
  +        this.markedForCascadingInsert = true;
  +    }
  +
  +    boolean isMarkedForCascadingDelete()
  +    {
  +        return markedForCascadingDelete;
  +    }
  +
  +    void markForCascadingDelete()
  +    {
  +        this.markedForCascadingDelete = true;
  +    }
  +
       ClassDescriptor getClassDescriptor()
       {
           return getBroker().getClassDescriptor(ProxyHelper.getRealClass(getObject()));
  @@ -710,7 +730,7 @@
               RuntimeObject rt = new RuntimeObject(refObjOrProxy, getTx());
               // we don't use cascade locking, because new reference object
               // will be detected by ObjectEnvelopeTable#cascadeMarkedForInsert()
  -            getTx().lockAndRegister(rt, TransactionExt.READ, false, getTx().getRegistrationList());
  +            getTx().lockAndRegister(rt, TransactionExt.READ, false);
           }
           // in any case we need to link the main object
           addLinkOneToOne(ord, false);
  @@ -776,10 +796,12 @@
               // we have to link the new object
               mod.addLinkOneToN(cod, getObject(), false);
           }
  -        if(mod.needsInsert())
  -        {
  -            buffer.addForInsertDependent(mod);
  -        }
  +// arminw: this object will be matched again in ObjectEnvelopeTable#cascadingDependents()
  +// and then be added
  +//        if(mod.needsInsert())
  +//        {
  +//            buffer.addForInsertDependent(mod);
  +//        }
       }
   
       public void deletedXToN(CollectionDescriptor cod, Object refObjOrProxy, Identity oid)
  @@ -795,7 +817,9 @@
                   if(cascade)
                   {
                       mod.setModificationState(mod.getModificationState().markDelete());
  -                    buffer.addForDeletionDependent(mod);
  +                    // arminw: this object will be matched again in ObjectEnvelopeTable#cascadingDependents()
  +                    // and then be added
  +                    //buffer.addForDeletionDependent(mod);
                   }
                   if(cod.isMtoNRelation())
                   {
  
  
  
  1.1.2.10  +8 -13     db-ojb/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java
  
  Index: ObjectEnvelopeOrdering.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/ObjectEnvelopeOrdering.java,v
  retrieving revision 1.1.2.9
  retrieving revision 1.1.2.10
  diff -u -r1.1.2.9 -r1.1.2.10
  --- ObjectEnvelopeOrdering.java	21 Dec 2005 22:29:21 -0000	1.1.2.9
  +++ ObjectEnvelopeOrdering.java	31 Dec 2005 18:51:58 -0000	1.1.2.10
  @@ -18,7 +18,6 @@
   import java.util.ArrayList;
   import java.util.Iterator;
   import java.util.List;
  -import java.util.Map;
   
   import org.apache.commons.lang.ArrayUtils;
   import org.apache.commons.lang.builder.ToStringBuilder;
  @@ -86,24 +85,20 @@
       private static Logger log = LoggerFactory.getLogger(ObjectEnvelopeOrdering.class);
   
       private List originalOrder;
  -    private Map envelopes;
   
       private Vertex[] vertices;
       private List edgeList;
   
  -    private Identity[] newOrder;
  +    private ObjectEnvelope[] newOrder;
   
       /**
        * Creates an object envelope ordering based on an original ordering
        * of Identity objects and an Identity-&gt;ObjectEnvelope map
        * @param originalOrder a list of Identity objects
  -     * @param envelopes a map with ObjectEnvelope-s with their respective
  -     *      Identity-s as key
        */
  -    public ObjectEnvelopeOrdering(List originalOrder, Map envelopes)
  +    public ObjectEnvelopeOrdering(List originalOrder)
       {
           this.originalOrder = originalOrder;
  -        this.envelopes = envelopes;
       }
   
       /**
  @@ -120,7 +115,7 @@
           {
               t1 = System.currentTimeMillis();
           }
  -        newOrder = new Identity[originalOrder.size()];
  +        newOrder = new ObjectEnvelope[originalOrder.size()];
   
           if(log.isDebugEnabled()) log.debug("Orginal order: " + originalOrder);
           // set up the vertex array in the order the envelopes were added
  @@ -128,7 +123,7 @@
           // int vertexIndex = 0;
           for (Iterator it = originalOrder.iterator(); it.hasNext();)
           {
  -            ObjectEnvelope envelope = (ObjectEnvelope) envelopes.get(it.next());
  +            ObjectEnvelope envelope = (ObjectEnvelope) it.next();
               if (envelope.needsUpdate() || envelope.needsInsert() || envelope.needsDelete())
               {
                   Vertex vertex = new Vertex(envelope);
  @@ -141,7 +136,7 @@
               else
               {
                   // envelope is clean - just add identity to new order
  -                newOrder[newOrderIndex++] = envelope.getIdentity();
  +                newOrder[newOrderIndex++] = envelope;
                   if (log.isDebugEnabled())
                   {
                       log.debug("Add unmodified object "+envelope.getIdentity()+" to new OrderList");
  @@ -210,7 +205,7 @@
                   Vertex vertex = vertices[i];
                   if (!vertex.isProcessed() && vertex.getIncomingEdgeWeight() == minIncomingEdgeWeight)
                   {
  -                    newOrder[newOrderIndex++] = vertex.getEnvelope().getIdentity();
  +                    newOrder[newOrderIndex++] = vertex.getEnvelope();
                       vertex.markProcessed();
                       processCount++;
                       if (log.isDebugEnabled())
  @@ -244,7 +239,7 @@
        * @return an array of Identity objects representing the opimized sequence
        *      of database operations
        */
  -    public Identity[] getOrdering()
  +    public ObjectEnvelope[] getOrdering()
       {
           if (newOrder == null)
           {
  
  
  
  1.32.2.28 +161 -195  db-ojb/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java
  
  Index: ObjectEnvelopeTable.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java,v
  retrieving revision 1.32.2.27
  retrieving revision 1.32.2.28
  diff -u -r1.32.2.27 -r1.32.2.28
  --- ObjectEnvelopeTable.java	21 Dec 2005 22:29:21 -0000	1.32.2.27
  +++ ObjectEnvelopeTable.java	31 Dec 2005 18:51:58 -0000	1.32.2.28
  @@ -49,7 +49,7 @@
   import org.odmg.TransactionAbortedException;
   
   /**
  - * manages all ObjectEnvelopes included by a transaction.
  + * Manages all ObjectEnvelopes included by a transaction.
    * Performs commit, and rollack operations on all included Envelopes.
    *
    * @author Thomas Mahler
  @@ -58,10 +58,10 @@
    *         MBAIRD: added explicit closing and de-referencing to prevent any
    *         GC issues.
    */
  -public class ObjectEnvelopeTable
  +class ObjectEnvelopeTable
   {
       private Logger log = LoggerFactory.getLogger(ObjectEnvelopeTable.class);
  -    private TransactionImpl transaction;
  +    private final TransactionImpl transaction;
   
       /**
        * A list of {@link org.apache.ojb.broker.Identity} objects which are
  @@ -69,29 +69,32 @@
        * as "delete". E.g. if a collection reference C is moved from object A1 to A2,
        * then A1 wants to "delete" C and A2 wants to mark the new C object as "new".
        */
  -    private List newAssociatedIdentites = new ArrayList();
  -    private List m2nLinkList = new ArrayList();
  -    private List m2nUnlinkList = new ArrayList();
  -    private List markedForDeletionList = new ArrayList();
  -    private List markedForInsertList = new ArrayList();
  -
  -    /** the internal table mapping Objects to their ObjectTransactionWrappers */
  -    private Map mhtObjectEnvelopes = new HashMap();
  +    private final List newAssociatedIdentites = new ArrayList();
  +    private final List m2nLinkList = new ArrayList();
  +    private final List m2nUnlinkList = new ArrayList();
   
       /**
  -     * a vector containing the ObjectEnvelope objects representing modifications
  +     * This internal table map the object identity to the object
  +     * transactional wrapper. This map is associated with the
  +     * {@link #objectEnvelopesOrderList}.
  +     */
  +    private Map objectEnvelopesMap;
  +    /**
  +     * a list containing the ObjectEnvelope objects representing modifications
        * in the order they were added. If an ObjectEnvelope is added twice, only
  -     * the the second addition is ignored.
  +     * the the second addition is ignored. This list is associated with
  +     * the {@link #objectEnvelopesMap}.
        */
  -    private ArrayList mvOrderOfIds = new ArrayList();
  +    private ArrayList objectEnvelopesOrderList;
   
       /** marker used to avoid superfluous reordering and commiting */
  -    private boolean needsCommit = false;
  +    private boolean needsCommit;
   
       /** Creates new ObjectEnvelopeTable */
  -    public ObjectEnvelopeTable(TransactionImpl myTransaction)
  +    ObjectEnvelopeTable(TransactionImpl myTransaction)
       {
           transaction = myTransaction;
  +        prepareForUse();
       }
   
       TransactionImpl getTransaction()
  @@ -99,22 +102,59 @@
           return transaction;
       }
   
  -    /** prepare this instance for reuse */
  -    public void refresh()
  +    /** prepare this instance for re-/use */
  +    void prepareForUse()
       {
           needsCommit = false;
  -        mhtObjectEnvelopes = new HashMap();
  -        mvOrderOfIds = new ArrayList();
  -        afterWriteCleanup();
  +        objectEnvelopesMap = new HashMap();
  +        objectEnvelopesOrderList = new ArrayList();
  +        linkCleanup();
  +    }
  +
  +    /**
  +     * Call this after the transaction is completed.
  +     */
  +    void afterTransactionCleanup()
  +    {
  +        this.objectEnvelopesMap = null;
  +        this.objectEnvelopesOrderList = null;
       }
   
  -    void afterWriteCleanup()
  -    {
  -        m2nLinkList.clear();
  -        m2nUnlinkList.clear();
  -        newAssociatedIdentites.clear();
  -        markedForDeletionList.clear();
  -        markedForInsertList.clear();
  +    /**
  +     * Call this after the objects are written to datastore.
  +     */
  +    private void linkCleanup()
  +    {
  +        if(m2nLinkList.size() > 0) m2nLinkList.clear();
  +        if(m2nUnlinkList.size() > 0) m2nUnlinkList.clear();
  +        if(newAssociatedIdentites.size() > 0) newAssociatedIdentites.clear();
  +    }
  +
  +    /**
  +     * This method have to be called to reuse all registered {@link ObjectEnvelope}
  +     * objects after transaction commit/flush/checkpoint call.
  +     */
  +    private void prepareForReuse(boolean reuse)
  +    {
  +        if(reuse)
  +        {
  +            // using clone to avoid ConcurentModificationException
  +            Iterator iter = ((List) objectEnvelopesOrderList.clone()).iterator();
  +            while(iter.hasNext())
  +            {
  +                ObjectEnvelope mod = (ObjectEnvelope) iter.next();
  +                if(!needsCommit || (mod.getModificationState() == StateOldClean.getInstance()
  +                        || mod.getModificationState().isTransient()))
  +                {
  +                    // nothing to do
  +                }
  +                else
  +                {
  +                    mod.setModificationState(mod.getModificationState().markClean());
  +                }
  +            }
  +        }
  +        linkCleanup();
       }
   
       /**
  @@ -139,12 +179,6 @@
                                   + "  broker was: "
                                   + broker);
               }
  -            // all neccessary db operations are executed within a PersistenceBroker transaction:
  -            if(!broker.isInTransaction())
  -            {
  -                log.error("PB associated with current odmg-tx is not in tx");
  -                throw new TransactionAbortedException("Underlying PB is not in tx, was begin call done before commit?");
  -            }
   
               // Committing has to be done in two phases. First implicitly upgrade to lock on all related
               // objects of objects in this transaction. Then the list of locked objects has to be
  @@ -167,12 +201,6 @@
   
               // 4. Reorder objects
               reorder();
  -//            System.out.println("## ordering: ");
  -//            for(int i = 0; i < mvOrderOfIds.size(); i++)
  -//            {
  -//                System.out.println("" + mvOrderOfIds.get(i));
  -//            }
  -//            System.out.println("## ordering end");
   
               // 5. write objects.
               writeAllEnvelopes(reuse);
  @@ -182,10 +210,6 @@
   
               // 7. Update all Envelopes to new CleanState
               prepareForReuse(reuse);
  -
  -            // 6. commit cleanup
  -            afterWriteCleanup();
  -
           }
           catch(Exception e)
           {
  @@ -230,10 +254,10 @@
   
           Iterator iter;
           // using clone to avoid ConcurentModificationException
  -        iter = ((List) mvOrderOfIds.clone()).iterator();
  +        iter = ((List) objectEnvelopesOrderList.clone()).iterator();
           while(iter.hasNext())
           {
  -            ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
  +            ObjectEnvelope mod = (ObjectEnvelope) iter.next();
               boolean insert = false;
               if(needsCommit)
               {
  @@ -241,7 +265,7 @@
                   mod.getModificationState().commit(mod);
                   if(reuse && insert)
                   {
  -                    getTransaction().doSingleLock(mod.getClassDescriptor(), mod.getObject(), mod.getIdentity(), Transaction.WRITE);
  +                    getTransaction().internalSingleLock(mod.getClassDescriptor(), mod.getObject(), mod.getIdentity(), Transaction.WRITE);
                   }
               }
               /*
  @@ -262,10 +286,10 @@
        */
       private void checkAllEnvelopes(PersistenceBroker broker)
       {
  -        Iterator iter = ((List) mvOrderOfIds.clone()).iterator();
  +        Iterator iter = ((List) objectEnvelopesOrderList.clone()).iterator();
           while(iter.hasNext())
           {
  -            ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
  +            ObjectEnvelope mod = (ObjectEnvelope) iter.next();
               // only non transient objects should be performed
               if(!mod.getModificationState().isTransient())
               {
  @@ -275,32 +299,6 @@
       }
   
       /**
  -     * This method have to be called to reuse all registered {@link ObjectEnvelope}
  -     * objects after transaction commit/flush/checkpoint call.
  -     */
  -    private void prepareForReuse(boolean reuse)
  -    {
  -        if(reuse)
  -        {
  -            // using clone to avoid ConcurentModificationException
  -            Iterator iter = ((List) mvOrderOfIds.clone()).iterator();
  -            while(iter.hasNext())
  -            {
  -                ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
  -                if(!needsCommit || (mod.getModificationState() == StateOldClean.getInstance()
  -                        || mod.getModificationState().isTransient()))
  -                {
  -                    // nothing to do
  -                }
  -                else
  -                {
  -                    mod.setModificationState(mod.getModificationState().markClean());
  -                }
  -            }
  -        }
  -    }
  -
  -    /**
        * Checks the status of all modified objects and
        * upgrade the lock if needed, cleanup the {@link ObjectEnvelope}
        * objects.
  @@ -308,12 +306,12 @@
       private void upgradeLockIfNeeded()
       {
           // using clone to avoid ConcurentModificationException
  -        Iterator iter = ((List) mvOrderOfIds.clone()).iterator();
  +        Iterator iter = ((List) objectEnvelopesOrderList.clone()).iterator();
           TransactionImpl tx = getTransaction();
           ObjectEnvelope mod;
           while(iter.hasNext())
           {
  -            mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
  +            mod = (ObjectEnvelope) iter.next();
               // ignore transient objects
               if(!mod.getModificationState().isTransient())
               {
  @@ -333,7 +331,7 @@
                           // if the object isn't already locked, we will do it now
                           if(!mod.isWriteLocked())
                           {
  -                            tx.doSingleLock(cld, mod.getObject(), mod.getIdentity(), Transaction.WRITE);
  +                            tx.internalSingleLock(cld, mod.getObject(), mod.getIdentity(), Transaction.WRITE);
                           }
                       }
                   }
  @@ -350,10 +348,10 @@
       {
           try
           {
  -            Iterator iter = mvOrderOfIds.iterator();
  +            Iterator iter = objectEnvelopesOrderList.iterator();
               while(iter.hasNext())
               {
  -                ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
  +                ObjectEnvelope mod = (ObjectEnvelope) iter.next();
                   if(log.isDebugEnabled())
                       log.debug("rollback: " + mod);
                   // if the Object has been modified by transaction, mark object as dirty
  @@ -368,7 +366,6 @@
           {
               needsCommit = false;
           }
  -        afterWriteCleanup();
       }
   
       /** remove an objects entry from the object registry */
  @@ -383,8 +380,8 @@
           {
               id = transaction.getBroker().serviceIdentity().buildIdentity(pKey);
           }
  -        mhtObjectEnvelopes.remove(id);
  -        mvOrderOfIds.remove(id);
  +        Object toRemove = objectEnvelopesMap.remove(id);
  +        objectEnvelopesOrderList.remove(toRemove);
       }
   
       /**
  @@ -395,13 +392,19 @@
        */
       public Enumeration elements()
       {
  -        return java.util.Collections.enumeration(mhtObjectEnvelopes.values());
  +        return java.util.Collections.enumeration(objectEnvelopesMap.values());
       }
   
       /** retrieve an objects ObjectModification state from the hashtable */
       public ObjectEnvelope getByIdentity(Identity id)
       {
  -        return (ObjectEnvelope) mhtObjectEnvelopes.get(id);
  +        return (ObjectEnvelope) objectEnvelopesMap.get(id);
  +    }
  +
  +    /** retrieve an objects ObjectModification state from the hashtable */
  +    public boolean contains(Identity oid)
  +    {
  +        return objectEnvelopesMap.containsKey(oid);
       }
   
       /**
  @@ -429,10 +432,9 @@
           if(result == null)
           {
               result = new ObjectEnvelope(this, oid, pKey, isNew);
  -            mhtObjectEnvelopes.put(oid, result);
  -            mvOrderOfIds.add(oid);
  -            if(log.isDebugEnabled())
  -                log.debug("register: " + result);
  +            objectEnvelopesMap.put(oid, result);
  +            objectEnvelopesOrderList.add(result);
  +            if(log.isDebugEnabled()) log.debug("Register: " + result);
           }
           return result;
       }
  @@ -453,45 +455,42 @@
           return buf.toString();
       }
   
  -    /** retrieve an objects ObjectModification state from the hashtable */
  -    public boolean contains(Identity oid)
  -    {
  -        //Integer keyInteger = new Integer(System.identityHashCode(key));
  -        return mhtObjectEnvelopes.containsKey(oid);
  -    }
  -
       /** Reorder the objects in the table to resolve referential integrity dependencies. */
       private void reorder()
       {
  -        if(getTransaction().isOrdering() && needsCommit && mhtObjectEnvelopes.size() > 1)
  +        if(getTransaction().isOrdering() && needsCommit && objectEnvelopesMap.size() > 1)
           {
  -            ObjectEnvelopeOrdering ordering = new ObjectEnvelopeOrdering(mvOrderOfIds, mhtObjectEnvelopes);
  +            ObjectEnvelopeOrdering ordering = new ObjectEnvelopeOrdering(objectEnvelopesOrderList);
               ordering.reorder();
  -            Identity[] newOrder = ordering.getOrdering();
  +            ObjectEnvelope[] newOrder = ordering.getOrdering();
   
  -            mvOrderOfIds.clear();
  +            objectEnvelopesOrderList.clear();
               for(int i = 0; i < newOrder.length; i++)
               {
  -                mvOrderOfIds.add(newOrder[i]);
  +                objectEnvelopesOrderList.add(newOrder[i]);
               }
           }
       }
   
       void cascadingDependents()
       {
  -        Iterator it = mhtObjectEnvelopes.values().iterator();
  +        Iterator it = objectEnvelopesMap.values().iterator();
           ObjectEnvelope mod;
  +        List markedForDeletion = null;
  +        List markedForInsert = null;
           // first we search for all deleted/insert objects
           while(it.hasNext())
           {
               mod = (ObjectEnvelope) it.next();
               if(mod.needsDelete())
               {
  -                addForDeletionDependent(mod);
  +                if(markedForDeletion == null) markedForDeletion = new ArrayList();
  +                markedForDeletion.add(mod);
               }
               else if(mod.needsInsert())
               {
  -                addForInsertDependent(mod);
  +                if(markedForInsert == null) markedForInsert = new ArrayList();
  +                markedForInsert.add(mod);
               }
           }
           /*
  @@ -501,63 +500,51 @@
           the proxy was materialized on deletion of the main object, but on performing
           the cascading insert the collection objects will be found and assigned to the new object.
           */
  -        cascadeMarkedForDeletion();
  -        cascadeMarkedForInsert();
  -    }
  -
  -    void addNewAssociatedIdentity(Identity oid)
  -    {
  -        newAssociatedIdentites.add(oid);
  -    }
  -
  -    boolean isNewAssociatedObject(Identity oid)
  -    {
  -        return newAssociatedIdentites.contains(oid);
  -    }
  -
  -    void addForInsertDependent(ObjectEnvelope mod)
  -    {
  -        markedForInsertList.add(mod);
  -    }
  -
  -    /** Starts recursive insert on all insert objects object graph */
  -    private void cascadeMarkedForInsert()
  -    {
  -        // This list was used to avoid endless recursion on circular references
  -        List alreadyPrepared = new ArrayList();
  -        for(int i = 0; i < markedForInsertList.size(); i++)
  +        if(markedForDeletion != null)
           {
  -            ObjectEnvelope mod = (ObjectEnvelope) markedForInsertList.get(i);
  -            // only if a new object was found we cascade to register the dependent objects
  -            if(mod.needsInsert())
  +            /* Starts recursive delete on all delete objects object graph */
  +            for(int i = 0; i < markedForDeletion.size(); i++)
               {
  -                cascadeInsertFor(mod, alreadyPrepared);
  -                alreadyPrepared.clear();
  +                mod = (ObjectEnvelope) markedForDeletion.get(i);
  +                // if the object wasn't associated with another object, start cascade delete
  +                if(!isNewAssociatedObject(mod.getIdentity()))
  +                {
  +                    cascadeDeleteFor(mod);
  +                }
  +            }
  +        }
  +        if(markedForInsert != null)
  +        {
  +            /* Starts recursive insert on all insert objects object graph */
  +            for(int i = 0; i < markedForInsert.size(); i++)
  +            {
  +                mod = (ObjectEnvelope) markedForInsert.get(i);
  +                // we expect that the list only contains objects for insert
  +                cascadeInsertFor(mod);
               }
           }
  -        markedForInsertList.clear();
       }
   
       /**
        * Walk through the object graph of the specified insert object. Was used for
        * recursive object graph walk.
        */
  -    private void cascadeInsertFor(ObjectEnvelope mod, List alreadyPrepared)
  +    private void cascadeInsertFor(ObjectEnvelope mod)
       {
  -        // avoid endless recursion, so use List for registration
  -        if(alreadyPrepared.contains(mod.getIdentity())) return;
  -        alreadyPrepared.add(mod.getIdentity());
  +        // avoid endless recursion
  +        if(mod.isMarkedForCascadingInsert()) return;
  +        mod.markForCascadingInsert();
   
           ClassDescriptor cld = getTransaction().getBroker().getClassDescriptor(mod.getObject().getClass());
   
           List refs = cld.getObjectReferenceDescriptors(true);
  -        cascadeInsertSingleReferences(mod, refs, alreadyPrepared);
  +        cascadeInsertSingleReferences(mod, refs);
   
           List colls = cld.getCollectionDescriptors(true);
  -        cascadeInsertCollectionReferences(mod, colls, alreadyPrepared);
  +        cascadeInsertCollectionReferences(mod, colls);
       }
   
  -    private void cascadeInsertSingleReferences(ObjectEnvelope source, List descriptor, List alreadyPrepared)
  +    private void cascadeInsertSingleReferences(ObjectEnvelope source, List descriptor)
       {
           for(int i = 0; i < descriptor.size(); i++)
           {
  @@ -583,25 +570,23 @@
                       {
                           rt = new RuntimeObject(depObj, getTransaction());
                       }
  +
                       Identity oid = rt.getIdentity();
  -                    if(!alreadyPrepared.contains(oid))
  +                    ObjectEnvelope depMod = getByIdentity(oid);
  +                    // if the object isn't registered and is a new
  +                    // object, register it - else we have nothing to do
  +                    if(depMod == null && rt.isNew())
                       {
  -                        ObjectEnvelope depMod = getByIdentity(oid);
  -                        // if the object isn't registered and is a new object, register it
  -                        // else we have nothing to do
  -                        if(depMod == null && rt.isNew())
  -                        {
  -                            getTransaction().lockAndRegister(rt, Transaction.WRITE, false, getTransaction().getRegistrationList());
  -                            depMod = getByIdentity(oid);
  -                            cascadeInsertFor(depMod, alreadyPrepared);
  -                        }
  +                        getTransaction().lockAndRegister(rt, Transaction.WRITE, false);
  +                        depMod = getByIdentity(oid);
  +                        cascadeInsertFor(depMod);
                       }
                   }
               }
           }
       }
   
  -    private void cascadeInsertCollectionReferences(ObjectEnvelope source, List descriptor, List alreadyPrepared)
  +    private void cascadeInsertCollectionReferences(ObjectEnvelope source, List descriptor)
       {
           // PersistenceBroker pb = getTransaction().getBroker();
           for(int i = 0; i < descriptor.size(); i++)
  @@ -643,7 +628,7 @@
                               ObjectEnvelope oe = getByIdentity(oid);
                               if(oe == null)
                               {
  -                                getTransaction().lockAndRegister(rt, Transaction.WRITE, false, getTransaction().getRegistrationList());
  +                                getTransaction().lockAndRegister(rt, Transaction.WRITE, false);
                                   oe = getByIdentity(oid);
                               }
                               if(col.isMtoNRelation())
  @@ -661,7 +646,7 @@
                                   */
                                   oe.setModificationState(oe.getModificationState().markDirty());
                               }
  -                            cascadeInsertFor(oe, alreadyPrepared);
  +                            cascadeInsertFor(oe);
                           }
                       }
                   }
  @@ -669,49 +654,26 @@
           }
       }
   
  -    void addForDeletionDependent(ObjectEnvelope mod)
  -    {
  -        markedForDeletionList.add(mod);
  -    }
  -
  -    /** Starts recursive delete on all delete objects object graph */
  -    private void cascadeMarkedForDeletion()
  -    {
  -        List alreadyPrepared = new ArrayList();
  -        for(int i = 0; i < markedForDeletionList.size(); i++)
  -        {
  -            ObjectEnvelope mod = (ObjectEnvelope) markedForDeletionList.get(i);
  -            // if the object wasn't associated with another object, start cascade delete
  -            if(!isNewAssociatedObject(mod.getIdentity()))
  -            {
  -                cascadeDeleteFor(mod, alreadyPrepared);
  -                alreadyPrepared.clear();
  -            }
  -        }
  -        markedForDeletionList.clear();
  -    }
  -
       /**
        * Walk through the object graph of the specified delete object. Was used for
        * recursive object graph walk.
        */
  -    private void cascadeDeleteFor(ObjectEnvelope mod, List alreadyPrepared)
  +    private void cascadeDeleteFor(ObjectEnvelope mod)
       {
           // avoid endless recursion
  -        if(alreadyPrepared.contains(mod.getIdentity())) return;
  -
  -        alreadyPrepared.add(mod.getIdentity());
  +        if(mod.isMarkedForCascadingDelete()) return;
  +        mod.markForCascadingDelete();
   
           ClassDescriptor cld = getTransaction().getBroker().getClassDescriptor(mod.getObject().getClass());
   
           List refs = cld.getObjectReferenceDescriptors(true);
  -        cascadeDeleteSingleReferences(mod, refs, alreadyPrepared);
  +        cascadeDeleteSingleReferences(mod, refs);
   
           List colls = cld.getCollectionDescriptors(true);
  -        cascadeDeleteCollectionReferences(mod, colls, alreadyPrepared);
  +        cascadeDeleteCollectionReferences(mod, colls);
       }
   
  -    private void cascadeDeleteSingleReferences(ObjectEnvelope source, List descriptor, List alreadyPrepared)
  +    private void cascadeDeleteSingleReferences(ObjectEnvelope source, List descriptor)
       {
           for(int i = 0; i < descriptor.size(); i++)
           {
  @@ -728,14 +690,14 @@
                       {
                           ObjectEnvelope depMod = get(oid, depObj, false);
                           depMod.setModificationState(depMod.getModificationState().markDelete());
  -                        cascadeDeleteFor(depMod, alreadyPrepared);
  +                        cascadeDeleteFor(depMod);
                       }
                   }
               }
           }
       }
   
  -    private void cascadeDeleteCollectionReferences(ObjectEnvelope source, List descriptor, List alreadyPrepared)
  +    private void cascadeDeleteCollectionReferences(ObjectEnvelope source, List descriptor)
       {
           PersistenceBroker pb = getTransaction().getBroker();
           for(int i = 0; i < descriptor.size(); i++)
  @@ -761,7 +723,7 @@
                       if(cascadeDelete)
                       {
                           colMod.setModificationState(colMod.getModificationState().markDelete());
  -                        cascadeDeleteFor(colMod, alreadyPrepared);
  +                        cascadeDeleteFor(colMod);
                       }
                       else
                       {
  @@ -780,6 +742,16 @@
           }
       }
   
  +    void addNewAssociatedIdentity(Identity oid)
  +    {
  +        newAssociatedIdentites.add(oid);
  +    }
  +
  +    boolean isNewAssociatedObject(Identity oid)
  +    {
  +        return newAssociatedIdentites.contains(oid);
  +    }
  +
       void addM2NLinkEntry(CollectionDescriptor cod, Object leftSource, Object rightSource)
       {
           if(!cod.isMtoNRelation()) throw new OJBRuntimeException("Expect a m:n releation, but specified a 1:n");
  @@ -824,17 +796,11 @@
        */
       boolean replaceRegisteredIdentity(Identity newOid, Identity oldOid)
       {
  -        /*
  -        TODO: Find a better solution
  -        */
           boolean result = false;
  -        Object oe = mhtObjectEnvelopes.remove(oldOid);
  +        Object oe = objectEnvelopesMap.remove(oldOid);
           if(oe != null)
           {
  -            mhtObjectEnvelopes.put(newOid, oe);
  -            int index = mvOrderOfIds.indexOf(oldOid);
  -            mvOrderOfIds.remove(index);
  -            mvOrderOfIds.add(index, newOid);
  +            objectEnvelopesMap.put(newOid, oe);
               result = true;
               if(log.isDebugEnabled()) log.debug("Replace identity: " + oldOid + " --replaced-by--> " + newOid);
           }
  
  
  
  1.59.2.27 +178 -176  db-ojb/src/java/org/apache/ojb/odmg/TransactionImpl.java
  
  Index: TransactionImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/odmg/TransactionImpl.java,v
  retrieving revision 1.59.2.26
  retrieving revision 1.59.2.27
  diff -u -r1.59.2.26 -r1.59.2.27
  --- TransactionImpl.java	31 Dec 2005 18:28:32 -0000	1.59.2.26
  +++ TransactionImpl.java	31 Dec 2005 18:51:59 -0000	1.59.2.27
  @@ -41,7 +41,7 @@
   import org.apache.ojb.broker.metadata.CollectionDescriptor;
   import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
   import org.apache.ojb.broker.util.BrokerHelper;
  -import org.apache.ojb.broker.util.GUID;
  +import org.apache.ojb.broker.util.GUIDFactory;
   import org.apache.ojb.broker.util.configuration.Configurable;
   import org.apache.ojb.broker.util.configuration.Configuration;
   import org.apache.ojb.broker.util.configuration.ConfigurationException;
  @@ -56,8 +56,7 @@
   import org.odmg.TransactionNotInProgressException;
   
   /**
  - *
  - * Implementation of Transaction for org.odmg.Transaction.
  + * Implementation of Transaction for {@link org.odmg.Transaction}.
    *
    * @author     Thomas Mahler & David Dixon-Peugh
    * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
  @@ -70,16 +69,19 @@
           implements Transaction, MaterializationListener, Configurable, CollectionProxyListener, TransactionExt
   {
       private Logger log = LoggerFactory.getLogger(TransactionImpl.class);
  +
  +    private static final GUIDFactory guid = new GUIDFactory();
  +
  +    private final String txGUID;
  +    private final ImplementationImpl implementation;
  +    private final NamedRootsMap namedRootsMap;
  +    protected PersistenceBrokerInternal broker = null;
  +    //private ArrayList registrationList = new ArrayList();
  +
       private boolean impliciteWriteLocks;
       private boolean implicitLocking;
       private boolean ordering;
   
  -    private String txGUID;
  -    protected PersistenceBrokerInternal broker = null;
  -    private ArrayList registrationList = new ArrayList();
  -    private ImplementationImpl implementation;
  -    private NamedRootsMap namedRootsMap;
  -
       /**
        * The status of the current transaction, as specified by the
        * javax.transaction package.
  @@ -91,7 +93,7 @@
        * the internal table containing all Objects "touched" by this tx and their
        * respective transactional state
        */
  -    protected ObjectEnvelopeTable objectEnvelopeTable = null;
  +    protected final ObjectEnvelopeTable objectEnvelopeTable;
   
       /**
        * reference to the currently opened database
  @@ -117,6 +119,11 @@
       private ArrayList unmaterializedLocks = new ArrayList();
   
       /**
  +     * This list is used to avoid endless loops on circular referenced objects.
  +     */
  +    private ArrayList currentRegistered = new ArrayList();
  +
  +    /**
        * Creates new Transaction
        * @param implementation The odmg Implementation class
        */
  @@ -126,12 +133,12 @@
           this.impliciteWriteLocks = implementation.isImpliciteWriteLocks();
           this.implicitLocking = implementation.isImplicitLocking();
           this.ordering = implementation.isOrdering();
  -        //this.noteUserOrdering = implementation.isNoteUserOrder();
  -
  -        // assign a globally uniqe id to this tx
  -        txGUID = new GUID().toString();
  +        // assign a uniqe id to this tx
  +        txGUID = guid.next();
           curDB = implementation.getCurrentDatabase();
           namedRootsMap = new NamedRootsMap(this);
  +        // initialize the ObjectEnvelope table
  +        objectEnvelopeTable = new ObjectEnvelopeTable(this);
       }
   
       public ImplementationImpl getImplementation()
  @@ -226,93 +233,142 @@
           if (log.isDebugEnabled()) log.debug("lock object was called on tx " + this + ", object is " + obj.toString());
           checkOpen();
           RuntimeObject rtObject = new RuntimeObject(obj, this);
  -        lockAndRegister(rtObject, lockMode, isImplicitLocking(), getRegistrationList());
  -//        if(isImplicitLocking()) moveToLastInOrderList(rtObject.getIdentity());
  -    }
  -
  -    /**
  -     * Returns an empty List for registration of processed object Identity.
  -     */
  -    public ArrayList getRegistrationList()
  -    {
  -        clearRegistrationList();
  -        return registrationList;
  +        lockAndRegister(rtObject, lockMode, isImplicitLocking());
       }
   
       /**
  -     * Clears the list of processed object Identity.
  +     * Lock and register the specified object, make sure that when cascading locking and register
  +     * is enabled to specify a List to register the already processed object Identiy.
        */
  -    public void clearRegistrationList()
  +    public void lockAndRegister(RuntimeObject rtObject, int lockMode)
       {
  -        registrationList.clear();
  +        lockAndRegister(rtObject, lockMode, isImplicitLocking());
       }
   
       /**
        * Lock and register the specified object, make sure that when cascading locking and register
        * is enabled to specify a List to register the already processed object Identiy.
        */
  -    public void lockAndRegister(RuntimeObject rtObject, int lockMode, List registeredObjects)
  +    public synchronized void lockAndRegister(RuntimeObject rtObject, int lockMode, boolean cascade)
       {
  -        lockAndRegister(rtObject, lockMode, isImplicitLocking(), registeredObjects);
  +        internalLockRegister(rtObject, lockMode, cascade);
  +        if(currentRegistered.size() > 0) currentRegistered.clear();
       }
   
       /**
        * Lock and register the specified object, make sure that when cascading locking and register
        * is enabled to specify a List to register the already processed object Identiy.
        */
  -    public synchronized void lockAndRegister(RuntimeObject rtObject, int lockMode, boolean cascade, List registeredObjects)
  +    private void internalLockRegister(RuntimeObject rtObject, int lockMode, boolean cascade)
       {
           if(log.isDebugEnabled()) log.debug("Lock and register called for " + rtObject.getIdentity());
           // if current object was already locked, do nothing
           // avoid endless loops when circular object references are used
  -        if(!registeredObjects.contains(rtObject.getIdentity()))
  +        Identity oid = rtObject.getIdentity();
  +        ObjectEnvelope mod = objectEnvelopeTable.getByIdentity(oid);
  +        if(mod == null && !currentRegistered.contains(oid))
           {
  -            if(cascade)
  -            {
  -                // if implicite locking is enabled, first add the current object to
  -                // list of registered objects to avoid endless loops on circular objects
  -                registeredObjects.add(rtObject.getIdentity());
  -                // lock and register 1:1 references first
  -                //
  -                // If implicit locking is used, we have materialize the main object
  -                // to lock the referenced objects too
  -                lockAndRegisterReferences(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, registeredObjects);
  -            }
  -            try
  +            currentRegistered.add(oid);
  +            Object objectToRegister = rtObject.getObj();
  +            /*
  +            if the object is a Proxy there are two options:
  +            1. The proxies real subject has already been materialized:
  +               we take this real subject as the object to register and proceed
  +               as if it were a ordinary object.
  +            2. The real subject has not been materialized: Then there is nothing
  +               to be registered now!
  +               Of course we might just materialize the real subject to have something
  +               to register. But this would make proxies useless for ODMG as proxies would
  +               get materialized even if their real subjects were not used by the
  +               client app.
  +               Thus we register the current transaction as a Listener to the IndirectionHandler
  +               of the Proxy.
  +               Only when the IndirectionHandler performs the materialization of the real subject
  +               at some later point in time it invokes callbacks on all it's listeners.
  +               Using this callback we can defer the registering until it's really needed.
  +            */
  +            if(rtObject.isProxy())
               {
  -                // perform the lock on the object
  -                // we don't need to lock new objects
  -                if(!rtObject.isNew())
  +                IndirectionHandler handler = rtObject.getHandler();
  +                if(handler == null)
  +                {
  +                    throw new OJBRuntimeException("Unexpected error, expect an proxy object as indicated: " + rtObject);
  +                }
  +                if (handler.alreadyMaterialized())
                   {
  -                    doSingleLock(rtObject.getCld(), rtObject.getObj(), rtObject.getIdentity(), lockMode);
  +                    objectToRegister = handler.getRealSubject();
  +                }
  +                else
  +                {
  +                    registerToIndirectionHandler(handler);
  +                    registerUnmaterializedLocks(rtObject);
  +                    // all work is done, so set to null
  +                    objectToRegister = null;
                   }
  -                // after we locked the object, register it to detect status and changes while tx
  -                doSingleRegister(rtObject, lockMode);
               }
  -            catch (Throwable t)
  +            if(objectToRegister != null)
               {
  -                //log.error("Locking of obj " + rtObject.getIdentity() + " failed", t);
  -                // if registering of object fails release lock on object, because later we don't
  -                // get a change to do this.
  -                implementation.getLockManager().releaseLock(this, rtObject.getIdentity(), rtObject.getObj());
  -                if(t instanceof LockNotGrantedException)
  +                if(cascade)
                   {
  -                    throw (LockNotGrantedException) t;
  +                    // lock and register 1:1 references first
  +                    //
  +                    // If implicit locking is used, we have to use the materialized main object
  +                    // to lock the referenced objects too
  +                    internalLockRegisterReferences(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, cascade);
                   }
  -                else
  +                try
  +                {
  +                    // perform the lock on the object
  +                    // we don't need to lock new objects
  +                    if(!rtObject.isNew())
  +                    {
  +                        internalSingleLock(rtObject.getCld(), rtObject.getObj(), rtObject.getIdentity(), lockMode);
  +                    }
  +                    // after we locked the object, register it to detect status and changes while tx
  +                    internalSingleRegister(rtObject, lockMode);
  +                }
  +                catch (Throwable t)
                   {
  -                    log.error("Unexpected failure while locking", t);
  -                    throw new LockNotGrantedException("Locking failed for "
  -                            + rtObject.getIdentity()+ ", nested exception is: [" + t.getClass().getName()
  -                            + ": " + t.getMessage() + "]");
  +                    //log.error("Locking of obj " + rtObject.getIdentity() + " failed", t);
  +                    // if registering of object fails release lock on object, because later we don't
  +                    // get a change to do this.
  +                    implementation.getLockManager().releaseLock(this, rtObject.getIdentity(), rtObject.getObj());
  +                    if(t instanceof LockNotGrantedException)
  +                    {
  +                        throw (LockNotGrantedException) t;
  +                    }
  +                    else
  +                    {
  +                        log.error("Unexpected failure while locking", t);
  +                        throw new LockNotGrantedException("Locking failed for "
  +                                + rtObject.getIdentity()+ ", nested exception is: [" + t.getClass().getName()
  +                                + ": " + t.getMessage() + "]");
  +                    }
  +                }
  +                if(cascade)
  +                {
  +                    // perform locks and register 1:n and m:n references
  +                    // If implicit locking is used, we have to use the materialized main object
  +                    // to lock the referenced objects too
  +                    internalLockRegisterCollections(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, cascade);
                   }
               }
  -            if(cascade)
  +        }
  +        else
  +        {
  +            /*
  +            TODO:
  +            Replace this intransparent detach/attach workaround with a
  +            real detach/attach service
  +            */
  +            if(mod != null)
               {
  -                // perform locks and register 1:n and m:n references
  -                // If implicit locking is used, we have materialize the main object
  -                // to lock the referenced objects too
  -                lockAndRegisterCollections(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, registeredObjects);
  +                // only use real objects, no proxy instances
  +                Object realObj = rtObject.getObjMaterialized();
  +                if(realObj != null)
  +                {
  +                    mod.refreshObjectIfNeeded(realObj);
  +                }
               }
           }
       }
  @@ -329,7 +385,7 @@
        *
        * @exception  LockNotGrantedException    Description of Exception
        */
  -    void doSingleLock(ClassDescriptor cld, Object obj, Identity oid, int lockMode) throws LockNotGrantedException
  +    void internalSingleLock(ClassDescriptor cld, Object obj, Identity oid, int lockMode) throws LockNotGrantedException
       {
           LockManager lm = implementation.getLockManager();
           if (cld.isAcceptLocks())
  @@ -405,7 +461,7 @@
           // now we have to perform the named objects
           namedRootsMap.performDeletion();
           namedRootsMap.performInsert();
  -        namedRootsMap.afterWriteCleanup();
  +        namedRootsMap.cleanup();
       }
   
       /**
  @@ -419,6 +475,7 @@
           performTransactionAwareBeforeRollback();
   
           // Now, we abort everything. . .
  +        namedRootsMap.cleanup();
           objectEnvelopeTable.rollback();
   
           // Now, we notify everything the abort is done.
  @@ -443,7 +500,8 @@
               //remove locks for objects which haven't been materialized yet
               for (Iterator it = unmaterializedLocks.iterator(); it.hasNext();)
               {
  -                lm.releaseLock(this, it.next());
  +                RuntimeObject rt = (RuntimeObject) it.next();
  +                lm.releaseLock(this, rt.getIdentity(), rt.getObj());
               }
   
               // this tx is no longer interested in materialization callbacks
  @@ -457,42 +515,28 @@
                */
               if (log.isDebugEnabled())
                   log.debug("Close Transaction and release current PB " + broker + " on tx " + this);
  +            txStatus = Status.STATUS_NO_TRANSACTION;
               // remove current thread from LocalTxManager
               // to avoid problems for succeeding calls of the same thread
               implementation.getTxManager().deregisterTx(this);
  -            // now cleanup and prepare for reuse
  -            refresh();
  +            // now cleanup the use broker instance
  +            cleanupBroker();
           }
       }
   
       /**
  -     * cleanup tx and prepare for reuse
  +     * Prepare this tx for reuse
        */
       protected void refresh()
       {
  -        if (log.isDebugEnabled())
  -                log.debug("Refresh this transaction for reuse: " + this);
  -        try
  -        {
  -            // we reuse ObjectEnvelopeTable instance
  -            objectEnvelopeTable.refresh();
  -        }
  -        catch (Exception e)
  -        {
  -            if (log.isDebugEnabled())
  -            {
  -                log.debug("error closing object envelope table : " + e.getMessage());
  -                e.printStackTrace();
  -            }
  -        }
  -        cleanupBroker();
  +        if (log.isDebugEnabled()) log.debug("Refresh this transaction for reuse: " + this);
  +        // we reuse ObjectEnvelopeTable instance
  +        objectEnvelopeTable.prepareForUse();
           // clear the temporary used named roots map
           // we should do that, because same tx instance
           // could be used several times
           broker = null;
  -        clearRegistrationList();
  -        unmaterializedLocks.clear();
  -        txStatus = Status.STATUS_NO_TRANSACTION;
  +        if(unmaterializedLocks.size() > 0) unmaterializedLocks.clear();
       }
   
       /**
  @@ -581,7 +625,7 @@
               Object realObj = rt.getHandler().getRealSubject();
               rt = new RuntimeObject(realObj, rt.getIdentity(), this, false);
           }
  -        lockAndRegister(rt, Transaction.WRITE, getRegistrationList());
  +        lockAndRegister(rt, Transaction.WRITE);
           ObjectEnvelope oe = objectEnvelopeTable.getByIdentity(rt.getIdentity());
           // TODO: not needed on delete - or? When optimistic locking is used we should always use the
           // specified object instance to use the last version of the object
  @@ -628,7 +672,7 @@
       {
           try
           {
  -            lockAndRegister(rt, Transaction.WRITE, getRegistrationList());
  +            lockAndRegister(rt, Transaction.WRITE);
               markPersistent(rt);
           }
           catch (org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException ex)
  @@ -846,8 +890,7 @@
       {
           checkForBegin();
           if (log.isDebugEnabled()) log.debug("Begin transaction was called on tx " + this);
  -        // initialize the ObjectEnvelope table
  -        objectEnvelopeTable = new ObjectEnvelopeTable(this);
  +        refresh();
           // register transaction
           implementation.getTxManager().registerTx(this);
           // mark tx as active (open)
  @@ -870,6 +913,10 @@
           }
       }
   
  +    /**
  +     * Returns a global unique identifier for this transaction generated
  +     * by {@link org.apache.ojb.broker.util.GUIDFactory}.
  +     */
       public String getGUID()
       {
           return txGUID;
  @@ -901,78 +948,39 @@
        * Registers the object (without locking) with this transaction. This method
        * expects that the object was already locked, no check is done!!!
        */
  -    void doSingleRegister(RuntimeObject rtObject, int lockMode)
  +    private void internalSingleRegister(RuntimeObject rtObject, int lockMode)
               throws LockNotGrantedException, PersistenceBrokerException
       {
           if(log.isDebugEnabled()) log.debug("Register object " + rtObject.getIdentity());
  -        Object objectToRegister = rtObject.getObj();
  -        /*
  -        if the object is a Proxy there are two options:
  -        1. The proxies real subject has already been materialized:
  -           we take this real subject as the object to register and proceed
  -           as if it were a ordinary object.
  -        2. The real subject has not been materialized: Then there is nothing
  -           to be registered now!
  -           Of course we might just materialize the real subject to have something
  -           to register. But this would make proxies useless for ODMG as proxies would
  -           get materialized even if their real subjects were not used by the
  -           client app.
  -           Thus we register the current transaction as a Listener to the IndirectionHandler
  -           of the Proxy.
  -           Only when the IndirectionHandler performs the materialization of the real subject
  -           at some later point in time it invokes callbacks on all it's listeners.
  -           Using this callback we can defer the registering until it's really needed.
  -        */
  -        if(rtObject.isProxy())
  +        // no Proxy and is not null, register real object
  +        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(rtObject.getIdentity());
  +        // if we found an envelope, object is already registered --> we do nothing
  +        // than refreshing the object!
  +        if ((envelope == null))
           {
  -            IndirectionHandler handler = rtObject.getHandler();
  -            if(handler == null)
  -            {
  -                throw new OJBRuntimeException("Unexpected error, expect an proxy object as indicated: " + rtObject);
  -            }
  -            if (handler.alreadyMaterialized())
  -            {
  -                objectToRegister = handler.getRealSubject();
  -            }
  -            else
  -            {
  -                registerToIndirectionHandler(handler);
  -                registerUnmaterializedLocks(rtObject.getObj());
  -                // all work is done, so set to null
  -                objectToRegister = null;
  -            }
  +            // register object itself
  +            envelope = objectEnvelopeTable.get(rtObject.getIdentity(), rtObject.getObj(), rtObject.isNew());
           }
  -        // no Proxy and is not null, register real object
  -        if (objectToRegister != null)
  +        else
           {
  -            ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(rtObject.getIdentity());
  -            // if we found an envelope, object is already registered --> we do nothing
  -            // than refreshing the object!
  -            if ((envelope == null))
  -            {
  -                // register object itself
  -                envelope = objectEnvelopeTable.get(rtObject.getIdentity(), objectToRegister, rtObject.isNew());
  -            }
  -            else
  -            {
  -                /*
  -                arminw:
  -                if an different instance of the same object was locked again
  -                we should replace the old instance with new one to make
  -                accessible the changed fields
  -                */
  -                envelope.refreshObjectIfNeeded(objectToRegister);
  -            }
               /*
  +            TODO: replace this intransparent handling with detach/attach service
               arminw:
  -            For better performance we check if this object has already a write lock
  -            in this case we don't need to acquire a write lock on commit
  +            if an different instance of the same object was locked again
  +            we should replace the old instance with new one to make
  +            accessible the changed fields
               */
  -            if(lockMode == Transaction.WRITE)
  -            {
  -                // signal ObjectEnvelope that a WRITE lock is already acquired
  -                envelope.setWriteLocked(true);
  -            }
  +            envelope.refreshObjectIfNeeded(rtObject.getObj());
  +        }
  +        /*
  +        arminw:
  +        For better performance we check if this object has already a write lock
  +        in this case we don't need to acquire a write lock on commit
  +        */
  +        if(lockMode == Transaction.WRITE)
  +        {
  +            // signal ObjectEnvelope that a WRITE lock is already acquired
  +            envelope.setWriteLocked(true);
           }
       }
   
  @@ -981,7 +989,7 @@
        * reference locking, we will materialize objects and they will enter the registered for
        * lock map.
        */
  -    private void lockAndRegisterReferences(ClassDescriptor cld, Object sourceObject, int lockMode, List registeredObjects) throws LockNotGrantedException
  +    private void internalLockRegisterReferences(ClassDescriptor cld, Object sourceObject, int lockMode, boolean cascade) throws LockNotGrantedException
       {
           if (implicitLocking)
           {
  @@ -994,16 +1002,13 @@
                   {
                       boolean isProxy = ProxyHelper.isProxy(refObj);
                       RuntimeObject rt = isProxy ? new RuntimeObject(refObj, this, false) : new RuntimeObject(refObj, this);
  -                    if (!registrationList.contains(rt.getIdentity()))
  -                    {
  -                        lockAndRegister(rt, lockMode, registeredObjects);
  -                    }
  +                    internalLockRegister(rt, lockMode, cascade);
                   }
               }
           }
       }
   
  -    private void lockAndRegisterCollections(ClassDescriptor cld, Object sourceObject, int lockMode, List registeredObjects) throws LockNotGrantedException
  +    private void internalLockRegisterCollections(ClassDescriptor cld, Object sourceObject, int lockMode, boolean cascade) throws LockNotGrantedException
       {
           if (implicitLocking)
           {
  @@ -1048,10 +1053,7 @@
                                       item = handler.getRealSubject();
                                   }
                               }
  -                            if (!registrationList.contains(rt.getIdentity()))
  -                            {
  -                                lockAndRegister(rt, lockMode, registeredObjects);
  -                            }
  +                            internalLockRegister(rt, lockMode, cascade);
                           }
                       }
                       catch (LockNotGrantedException e)
  @@ -1106,7 +1108,7 @@
               }
               ClassDescriptor cld = getBroker().getClassDescriptor(materializedObject.getClass());
               RuntimeObject rt = new RuntimeObject(materializedObject, oid, cld, false, false);
  -            lockAndRegister(rt, Transaction.READ, isImplicitLocking(), getRegistrationList());
  +            lockAndRegister(rt, Transaction.READ, isImplicitLocking());
           }
           catch (Throwable t)
           {
  @@ -1156,9 +1158,9 @@
        * register proxy objects that were locked but haven't been materialized yet
        * so they can be unlocked when closing the transaction
        */
  -    protected void registerUnmaterializedLocks(Object obj)
  +    protected void registerUnmaterializedLocks(RuntimeObject rtObj)
       {
  -        unmaterializedLocks.add(obj);
  +        unmaterializedLocks.add(rtObj);
       }
   
       /**
  @@ -1174,7 +1176,7 @@
        */
       public PersistenceBrokerInternal getBrokerInternal()
       {
  -        if (broker == null || broker.isClosed())
  +        if (broker == null)
           {
               checkOpen();
               try
  @@ -1203,7 +1205,7 @@
        */
       protected boolean hasBroker()
       {
  -        return broker != null && !broker.isClosed();
  +        return broker != null; //&& !broker.isClosed();
       }
   
       protected void cleanupBroker()
  @@ -1276,7 +1278,7 @@
                   Identity oid = getBroker().serviceIdentity().buildIdentity(o);
                   ClassDescriptor cld = getBroker().getClassDescriptor(ProxyHelper.getRealClass(o));
                   RuntimeObject rt = new RuntimeObject(o, oid, cld, false, ProxyHelper.isProxy(o));
  -                lockAndRegister(rt, Transaction.READ, isImplicitLocking(), getRegistrationList());
  +                lockAndRegister(rt, Transaction.READ, isImplicitLocking());
               }
           }
           unregisterFromCollectionProxy(colProxy);
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org