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 2006/07/15 16:28:05 UTC
svn commit: r422235 [2/3] - in /db/ojb/trunk/src: java/org/apache/ojb/odmg/
java/org/apache/ojb/odmg/oql/ java/org/apache/ojb/odmg/states/
java/org/odmg/ jdori/org/apache/ojb/jdori/sql/
samples/org/apache/ojb/tutorials/
Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java?rev=422235&r1=422234&r2=422235&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/ObjectEnvelopeTable.java Sat Jul 15 07:28:03 2006
@@ -1,6 +1,6 @@
package org.apache.ojb.odmg;
-/* Copyright 2002-2004 The Apache Software Foundation
+/* Copyright 2002-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,12 +24,12 @@
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
+import org.apache.commons.lang.SystemUtils;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.OJBRuntimeException;
import org.apache.ojb.broker.OptimisticLockException;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerInternal;
-import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
import org.apache.ojb.broker.core.proxy.CollectionProxy;
import org.apache.ojb.broker.core.proxy.IndirectionHandler;
import org.apache.ojb.broker.metadata.ClassDescriptor;
@@ -40,27 +40,20 @@
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.odmg.link.LinkEntry;
import org.apache.ojb.odmg.link.LinkEntryMtoN;
-import org.apache.ojb.odmg.states.StateOldClean;
-import org.apache.ojb.odmg.states.StateTransient;
+import org.apache.ojb.odmg.states.ModificationState;
import org.odmg.LockNotGrantedException;
import org.odmg.ODMGRuntimeException;
import org.odmg.Transaction;
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
- * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
- *
- * 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
@@ -68,35 +61,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();
+ private final List newAssociatedIdentites = new ArrayList();
+ private final List m2nLinkList = new ArrayList();
+ private final List m2nUnlinkList = new ArrayList();
/**
- * the internal table mapping Objects to their ObjectTransactionWrappers
+ * This internal table map the object identity to the object
+ * transactional wrapper. This map is associated with the
+ * {@link #objectEnvelopesOrderList}.
*/
- private Map mhtObjectEnvelopes = new HashMap();
-
+ private Map objectEnvelopesMap;
/**
- * a vector containing the ObjectEnvelope objects representing modifications
+ * 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;
+ /** marker used to avoid superfluous reordering and commiting */
+ private boolean needsCommit;
- /**
- * Creates new ObjectEnvelopeTable
- */
- public ObjectEnvelopeTable(TransactionImpl myTransaction)
+ /** Creates new ObjectEnvelopeTable */
+ ObjectEnvelopeTable(TransactionImpl myTransaction)
{
transaction = myTransaction;
+ prepareForUse();
}
TransactionImpl getTransaction()
@@ -105,23 +95,66 @@
}
/**
- * prepare this instance for reuse
+ * Returns the number of registered objects.
*/
- public void refresh()
+ public int registeredObjectCount()
+ {
+ return objectEnvelopesMap.size();
+ }
+
+ /** prepare this instance for re-/use */
+ void prepareForUse()
{
needsCommit = false;
- mhtObjectEnvelopes = new HashMap();
- mvOrderOfIds = new ArrayList();
- afterWriteCleanup();
+ objectEnvelopesMap = new HashMap();
+ objectEnvelopesOrderList = new ArrayList();
+ linkCleanup();
}
- void afterWriteCleanup()
- {
- m2nLinkList.clear();
- m2nUnlinkList.clear();
- newAssociatedIdentites.clear();
- markedForDeletionList.clear();
- markedForInsertList.clear();
+ /**
+ * Call this after the transaction is completed.
+ */
+ void afterTransactionCleanup()
+ {
+ this.objectEnvelopesMap = null;
+ this.objectEnvelopesOrderList = null;
+ }
+
+ /**
+ * 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();
+ ModificationState state = mod.getModificationState();
+ if(!needsCommit || (state.isClean() && !state.isNew()) || state.isTransient())
+ {
+ // nothing to do
+ }
+ else
+ {
+ mod.setModificationState(state.markClean());
+ }
+ }
+ }
+ linkCleanup();
}
/**
@@ -133,24 +166,17 @@
public void writeObjects(boolean reuse) throws TransactionAbortedException, LockNotGrantedException
{
PersistenceBroker broker = transaction.getBroker();
- ConnectionManagerIF connMan = broker.serviceConnectionManager();
boolean saveBatchMode = broker.serviceBatchManager().isBatchMode();
try
{
- if (log.isDebugEnabled())
+ if(log.isDebugEnabled())
{
log.debug(
- "PB is in internal tx: "
- + broker.isInTransaction()
- + " 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?");
+ "PB is in internal tx: "
+ + broker.isInTransaction()
+ + " broker was: "
+ + broker);
}
// Committing has to be done in two phases. First implicitly upgrade to lock on all related
@@ -174,12 +200,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);
@@ -189,12 +209,8 @@
// 7. Update all Envelopes to new CleanState
prepareForReuse(reuse);
-
- // 6. commit cleanup
- afterWriteCleanup();
-
}
- catch (Exception e)
+ catch(Exception e)
{
broker.serviceBatchManager().cancelBatch();
/*
@@ -229,9 +245,7 @@
}
}
- /**
- * commit all envelopes against the current broker
- */
+ /** commit all envelopes against the current broker */
private void writeAllEnvelopes(boolean reuse)
{
// perform remove of m:n indirection table entries first
@@ -239,25 +253,26 @@
Iterator iter;
// using clone to avoid ConcurentModificationException
- iter = ((List) mvOrderOfIds.clone()).iterator();
- while (iter.hasNext())
- {
- ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
- if(needsCommit)
+ iter = ((List) objectEnvelopesOrderList.clone()).iterator();
+ while(iter.hasNext())
{
- boolean insert = mod.needsInsert();
- mod.getModificationState().commit(mod);
- if(reuse && insert)
- {
- getTransaction().doSingleLock(mod.getClassDescriptor(), mod.getObject(), mod.getIdentity(), Transaction.WRITE);
+ ObjectEnvelope mod = (ObjectEnvelope) iter.next();
+ boolean insert = false;
+ if(needsCommit)
+ {
+ insert = mod.needsInsert();
+ mod.getModificationState().commit(mod);
+ if(reuse && insert)
+ {
+ getTransaction().internalSingleLock(mod.getClassDescriptor(), mod.getIdentity(), Transaction.WRITE);
+ }
}
- }
- /*
- arminw: important to call this cleanup method for each registered
- ObjectEnvelope, because this method will e.g. remove proxy listener
- objects for registered objects.
- */
- mod.cleanup(reuse);
+ /*
+ arminw: important to call this cleanup method for each registered
+ ObjectEnvelope, because this method will e.g. remove proxy listener
+ objects for registered objects.
+ */
+ mod.cleanup(reuse, insert);
}
// add m:n indirection table entries
performM2NLinkEntries();
@@ -265,38 +280,22 @@
/**
* Mark objects no longer available in collection for delete and new objects for insert.
+ *
* @param broker the PB to persist all objects
*/
private void checkAllEnvelopes(PersistenceBroker broker)
{
- Iterator iter = ((List) mvOrderOfIds.clone()).iterator();
- while (iter.hasNext())
- {
- ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
- mod.markReferenceElements(broker);
- }
- }
-
- /**
- * 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)
+ Iterator iter = ((List) objectEnvelopesOrderList.clone()).iterator();
+ while(iter.hasNext())
{
- // using clone to avoid ConcurentModificationException
- Iterator iter = ((List) mvOrderOfIds.clone()).iterator();
- while (iter.hasNext())
+ ObjectEnvelope mod = (ObjectEnvelope) iter.next();
+ // transient and NewDelete objects must NOT performed
+ ModificationState state = mod.getModificationState();
+ if(!state.isTransient() && !(state.isNew() && state.isDelete()))
{
- ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
- mod.refreshObjectImage();
- if(needsCommit && (mod.getModificationState() != StateOldClean.getInstance() || mod.getModificationState() != StateTransient.getInstance()))
- {
- mod.setModificationState(mod.getModificationState().markClean());
- }
+ mod.markReferenceElements(broker);
}
- }
+ }
}
/**
@@ -307,49 +306,61 @@
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())
+ while(iter.hasNext())
{
- mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
- /*
- now we check if all modified objects has a write lock. On insert of new
- objects we don't need a write lock.
- */
- if(!mod.needsInsert())
+ mod = (ObjectEnvelope) iter.next();
+ // no need to lock new objects
+ if(mod.getModificationState().isNew())
{
- if((mod.needsDelete() || mod.needsUpdate()
- || mod.hasChanged(getTransaction().getBroker())))
+ needsCommit = true;
+ }
+ // ignore transient objects
+ else if(!mod.getModificationState().isTransient())
+ {
+ /*
+ now we check if all modified objects has a write lock. On insert of new
+ objects we don't need a write lock.
+ */
+ if(!mod.needsInsert())
+ {
+ if((mod.needsDelete() || mod.needsUpdate()
+ || mod.hasChanged(tx.getBroker())))
+ {
+ needsCommit = true;
+ // mark object dirty
+ mod.setModificationState(mod.getModificationState().markDirty());
+ ClassDescriptor cld = mod.getClassDescriptor();
+ // if the object isn't already locked, we will do it now
+ if(!mod.isWriteLocked())
+ {
+ tx.internalSingleLock(cld, mod.getIdentity(), Transaction.WRITE);
+ }
+ }
+ }
+ else
{
needsCommit = true;
- // mark object dirty
- mod.setModificationState(mod.getModificationState().markDirty());
- ClassDescriptor cld = mod.getClassDescriptor();
- if(!mod.isWriteLocked()) getTransaction().doSingleLock(cld, mod.getObject(), mod.getIdentity(), Transaction.WRITE);
}
}
- else
- {
- needsCommit = true;
- }
}
}
- /**
- * perform rollback on all tx-states
- */
+ /** perform rollback on all tx-states */
public void rollback()
{
try
{
- Iterator iter = mvOrderOfIds.iterator();
- while (iter.hasNext())
+ Iterator iter = objectEnvelopesOrderList.iterator();
+ while(iter.hasNext())
{
- ObjectEnvelope mod = (ObjectEnvelope) mhtObjectEnvelopes.get(iter.next());
- if (log.isDebugEnabled())
+ ObjectEnvelope mod = (ObjectEnvelope) iter.next();
+ if(log.isDebugEnabled())
log.debug("rollback: " + mod);
// if the Object has been modified by transaction, mark object as dirty
- if (mod.hasChanged(transaction.getBroker()))
+ if(mod.hasChanged(transaction.getBroker()))
{
mod.setModificationState(mod.getModificationState().markDirty());
}
@@ -360,16 +371,13 @@
{
needsCommit = false;
}
- afterWriteCleanup();
}
- /**
- * remove an objects entry from the Hashtable
- */
+ /** remove an objects entry from the object registry */
public void remove(Object pKey)
{
Identity id;
- if (pKey instanceof Identity)
+ if(pKey instanceof Identity)
{
id = (Identity) pKey;
}
@@ -377,8 +385,8 @@
{
id = transaction.getBroker().serviceIdentity().buildIdentity(pKey);
}
- mhtObjectEnvelopes.remove(id);
- mvOrderOfIds.remove(id);
+ Object toRemove = objectEnvelopesMap.remove(id);
+ objectEnvelopesOrderList.remove(toRemove);
}
/**
@@ -389,20 +397,25 @@
*/
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
- */
+ /** 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);
}
/**
* retrieve an objects ObjectEnvelope state from the hashtable.
* If no ObjectEnvelope is found, a new one is created and returned.
+ *
* @return the resulting ObjectEnvelope
*/
public ObjectEnvelope get(Object pKey, boolean isNew)
@@ -415,82 +428,74 @@
/**
* retrieve an objects ObjectEnvelope state from the hashtable.
* If no ObjectEnvelope is found, a new one is created and returned.
+ *
* @return the resulting ObjectEnvelope
*/
public ObjectEnvelope get(Identity oid, Object pKey, boolean isNew)
{
ObjectEnvelope result = getByIdentity(oid);
- if (result == null)
+ 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;
}
- /**
- * Returns a String representation of this object
- */
+ /** Returns a String representation of this object */
public String toString()
{
ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
- buf.append("### ObjectEnvelopeTable dump:");
+ String eol = SystemUtils.LINE_SEPARATOR;
+ buf.append("# ObjectEnvelopeTable dump:" + eol + "start[");
Enumeration en = elements();
- while (en.hasMoreElements())
+ while(en.hasMoreElements())
{
ObjectEnvelope mod = (ObjectEnvelope) en.nextElement();
- buf.append(mod.toString());
+ buf.append(mod.toString() + eol);
}
+ buf.append("]end");
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()
+ /** 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(
- getTransaction().getBrokerInternal(), mvOrderOfIds, mhtObjectEnvelopes);
+ ObjectEnvelopeOrdering ordering = new ObjectEnvelopeOrdering(objectEnvelopesOrderList);
ordering.reorder();
- Identity[] newOrder = ordering.getOrdering();
-
- mvOrderOfIds.clear();
- for (int i = 0; i < newOrder.length; i++)
+ ObjectEnvelope[] newOrder = ordering.getOrdering();
+
+ 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();
+ 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);
}
}
/*
@@ -498,67 +503,53 @@
then insert is mandatory, because the user could move unmaterialized
collection proxy objects from one existing, which was deleted, to a new object. In this case
the proxy was materialized on deletion of the main object, but on performing
- the cascading insert the collection objects will be found assigned to the new object.
+ 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)
+ {
+ /* Starts recursive delete on all delete objects object graph */
+ for(int i = 0; i < markedForDeletion.size(); i++)
+ {
+ 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)
{
- 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 insert on all insert objects object graph */
+ for(int i = 0; i < markedForInsert.size(); i++)
{
- cascadeInsertFor(mod, alreadyPrepared);
- alreadyPrepared.clear();
+ 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++)
{
@@ -567,7 +558,7 @@
if(depObj != null)
{
- // in any case we have to link the source object when the object is insert
+ // in any case we have to link the source object when the object needs insert
source.addLinkOneToOne(ord, false);
IndirectionHandler handler = getTransaction()
@@ -585,30 +576,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);
- }
- if(depMod == null)
- {
- // should never occur
- throw new RuntimeException("Unexpected behavior");
- }
- 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)
{
PersistenceBrokerInternal pb = getTransaction().getBrokerInternal();
for(int i = 0; i < descriptor.size(); i++)
@@ -626,7 +610,7 @@
Iterator it = BrokerHelper.getCollectionIterator(pb, collOrArray);
while(it.hasNext())
{
- Object colObj = it.next();
+ Object colObj = it.next();
if(colObj != null)
{
RuntimeObject rt = new RuntimeObject(colObj, getTransaction());
@@ -650,7 +634,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())
@@ -668,7 +652,7 @@
*/
oe.setModificationState(oe.getModificationState().markDirty());
}
- cascadeInsertFor(oe, alreadyPrepared);
+ cascadeInsertFor(oe);
}
}
}
@@ -676,51 +660,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++)
{
@@ -737,14 +696,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)
{
PersistenceBrokerInternal pb = getTransaction().getBrokerInternal();
for(int i = 0; i < descriptor.size(); i++)
@@ -752,19 +711,25 @@
CollectionDescriptor col = (CollectionDescriptor) descriptor.get(i);
boolean cascadeDelete = getTransaction().cascadeDeleteFor(col);
Object collOrArray = col.getPersistentField().get(source.getObject());
+ Iterator it = null;
if(collOrArray != null)
{
+ CollectionProxy proxy = pb.getProxyFactory().getCollectionProxy(collOrArray);
// on delete we have to materialize dependent objects
- Iterator it = BrokerHelper.getCollectionIterator(pb, collOrArray);
+ if(proxy != null) it = proxy.iterator();
+ else it = BrokerHelper.getCollectionIterator(pb, collOrArray);
+ }
+ if(it != null)
+ {
while(it.hasNext())
{
- Object colObj = pb.getProxyFactory().getRealObject(it.next());
+ Object colObj = pb.getProxyFactory().getRealObject(it.next());
Identity oid = pb.serviceIdentity().buildIdentity(colObj);
ObjectEnvelope colMod = get(oid, colObj, false);
if(cascadeDelete)
{
colMod.setModificationState(colMod.getModificationState().markDelete());
- cascadeDeleteFor(colMod, alreadyPrepared);
+ cascadeDeleteFor(colMod);
}
else
{
@@ -783,6 +748,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");
@@ -818,17 +793,27 @@
}
/**
- * Set the specified identity to the last position in the order list.
- * Note: The Identity must already exist in order list.
- */
- void moveToLastInOrderList(Identity oid)
- {
- int index = mvOrderOfIds.indexOf(oid);
- // move entry only if exists
- if(index > -1 && index < (mvOrderOfIds.size() - 1))
+ * Replace the {@link org.apache.ojb.broker.Identity}
+ * of a registered {@link ObjectEnvelope} object.
+ *
+ * @param newOid
+ * @param oldOid
+ * @return Returns <em>true</em> if successful.
+ */
+ boolean replaceRegisteredIdentity(Identity newOid, Identity oldOid)
+ {
+ boolean result = false;
+ Object oe = objectEnvelopesMap.remove(oldOid);
+ if(oe != null)
+ {
+ objectEnvelopesMap.put(newOid, oe);
+ result = true;
+ if(log.isDebugEnabled()) log.debug("Replace identity: " + oldOid + " --replaced-by--> " + newOid);
+ }
+ else
{
- Object id = mvOrderOfIds.remove(index);
- mvOrderOfIds.add(id);
+ log.warn("Can't replace unregistered object identity (" + oldOid + ") with new identity (" + newOid + ")");
}
+ return result;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/PBCapsule.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/PBCapsule.java?rev=422235&r1=422234&r2=422235&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/PBCapsule.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/PBCapsule.java Sat Jul 15 07:28:03 2006
@@ -1,14 +1,6 @@
package org.apache.ojb.odmg;
-import org.apache.ojb.broker.OJBRuntimeException;
-import org.apache.ojb.broker.PersistenceBroker;
-import org.apache.ojb.broker.PersistenceConfiguration;
-import org.apache.ojb.broker.util.logging.Logger;
-import org.apache.ojb.broker.util.logging.LoggerFactory;
-import org.odmg.ODMGRuntimeException;
-import org.odmg.Transaction;
-
-/* Copyright 2002-2004 The Apache Software Foundation
+/* Copyright 2002-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,15 +14,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+import org.apache.ojb.broker.OJBRuntimeException;
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PersistenceConfiguration;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+import org.odmg.ODMGRuntimeException;
+import org.odmg.Transaction;
+
+/**
+ * ONLY VALID FOR READ OPERATIONS! Capsulates the way to obtain
+ * PersistenceBroker instances when a odmg-tx is running or
+ * not - Do not forget to call the destroy() method after use.
+ * When a transaction was found we use the PersistenceBroker instance
+ * shipped with the Transaction (via {@link HasBroker}), else we try
+ * to obtain a broker using the given {@link PersistenceConfiguration}.
+ *
+ * @version $Id$
+ */
public final class PBCapsule
{
- private Logger log = LoggerFactory.getLogger(PBCapsule.class);
+ private static Logger log = LoggerFactory.getLogger(PBCapsule.class);
+ private PersistenceBroker broker;
private PersistenceConfiguration persistenceConf;
private Transaction tx;
- private PersistenceBroker broker;
private boolean needsTxCommit = false;
- private boolean needsPBCommit = false;
+ private boolean needsClose = false;
private boolean isIllegal = false;
public PBCapsule(PersistenceConfiguration persistenceConf, Transaction tx)
@@ -42,19 +53,13 @@
public PersistenceBroker getBroker()
{
- if (isIllegal)
- {
- throw new OJBRuntimeException("You could not reuse PBCapsule after destroy");
- }
+ if(isIllegal) throw new OJBRuntimeException("You could not reuse PBCapsule after destroy");
return broker;
}
private void prepare()
{
- if (isIllegal)
- {
- throw new OJBRuntimeException("You could not reuse PBCapsule after destroy");
- }
+ if(isIllegal) throw new OJBRuntimeException("You could not reuse PBCapsule after destroy");
if(tx == null && persistenceConf == null)
{
throw new ODMGRuntimeException("Invalid constructor arguments, both arguments are 'null'");
@@ -69,12 +74,7 @@
log.debug("No running transaction found, try to get PersistenceBroker instance from configuration " + persistenceConf);
}
broker = persistenceConf.createPersistenceBroker();
- // begin tx on the PB instance
- if (!broker.isInTransaction())
- {
- broker.beginTransaction();
- needsPBCommit = true;
- }
+ needsClose = true;
}
else
{
@@ -97,20 +97,13 @@
if (log.isDebugEnabled()) log.debug("Indicated to commit tx");
tx.commit();
}
- else if (needsPBCommit)
+ else if (needsClose)
{
- if (log.isDebugEnabled()) log.debug("Indicated to commit PersistenceBroker");
- try
- {
- broker.commitTransaction();
- }
- finally
- {
- if (broker != null) broker.close();
- }
+ if (log.isDebugEnabled()) log.debug("Indicated to close PersistenceBroker");
+ if (broker != null) broker.close();
}
isIllegal = true;
needsTxCommit = false;
- needsPBCommit = false;
+ needsClose = false;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java?rev=422235&r1=422234&r2=422235&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/RuntimeObject.java Sat Jul 15 07:28:03 2006
@@ -1,11 +1,5 @@
package org.apache.ojb.odmg;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.ojb.broker.Identity;
-import org.apache.ojb.broker.PersistenceBrokerInternal;
-import org.apache.ojb.broker.core.proxy.IndirectionHandler;
-import org.apache.ojb.broker.metadata.ClassDescriptor;
-
/* Copyright 2002-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +15,12 @@
* limitations under the License.
*/
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.core.proxy.IndirectionHandler;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+
/**
* Helper object encapsulates common used object properties/states, help to reduce
* needless metadata calls.
@@ -105,33 +105,7 @@
void doIsNewObjectCheck(final TransactionImpl tx)
{
- /*
- detection of new objects is costly (select of ID in DB to check if object
- already exists) we do:
- a. check if the object has nullified PK field
- b. check if the object is already registered
- c. lookup from cache and if not found, last option select on DB
- */
- final PersistenceBrokerInternal pb = tx.getBrokerInternal();
- boolean isNew = pb.serviceBrokerHelper().hasNullPKField(cld, obj);
- if(!isNew)
- {
- // use method call to guaratee creation of oid
- final Identity oid = getIdentity();
- final ObjectEnvelope mod = tx.objectEnvelopeTable.getByIdentity(oid);
- if(mod != null)
- {
- // already registered object, use current state
- isNew = mod.needsInsert();
- }
- else
- {
- // if object was found cache, assume it's old
- // else make costly check against the DB
- isNew = pb.serviceObjectCache().lookup(oid) == null
- && !pb.serviceJdbcAccess().doesExist(cld, oid);
- }
- }
+ boolean isNew = tx.isTransient(cld, obj, null);
this.isNew = isNew ? Boolean.TRUE : Boolean.FALSE;
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAbortedExceptionOJB.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAbortedExceptionOJB.java?rev=422235&r1=422234&r2=422235&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAbortedExceptionOJB.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAbortedExceptionOJB.java Sat Jul 15 07:28:03 2006
@@ -1,6 +1,6 @@
package org.apache.ojb.odmg;
-/* Copyright 2003-2004 The Apache Software Foundation
+/* Copyright 2003-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAware.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAware.java?rev=422235&r1=422234&r2=422235&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAware.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionAware.java Sat Jul 15 07:28:03 2006
@@ -1,6 +1,6 @@
package org.apache.ojb.odmg;
-/* Copyright 2002-2004 The Apache Software Foundation
+/* Copyright 2002-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
import java.io.Serializable;
/**
+ *
* TransactionAware is an interface that can be implemented
* to provide hooks into the Transaction interface provided
* by ObJectRelationalBridge.
@@ -60,32 +61,38 @@
*/
public interface TransactionAware extends Serializable
{
- static final long serialVersionUID = 3690863289834166023L;
-
- /**
+ static final long serialVersionUID = 3690863289834166023L; /**
+ *
* beforeCommit will give an object a chance to kill a
* transaction before it is committed.
* To kill a transaction, throw a new TransactionAbortedException.
+ *
*/
public void beforeCommit() throws org.odmg.TransactionAbortedException;
/**
+ *
* afterCommit is called only after a successful commit has taken
* place.
+ *
*/
public void afterCommit();
/**
+ *
* beforeAbort is called before a transaction is aborted.
+ *
*/
public void beforeAbort();
/**
+ *
* afterAbort will be called after a transaction has been aborted.
* The values of fields which get persisted will have changed to
* what they were at the begining of the transaction. This method
* should be overridden to reset any transient or non-persistent
* fields.
+ *
*/
public void afterAbort();
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java?rev=422235&r1=422234&r2=422235&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/odmg/TransactionExt.java Sat Jul 15 07:28:03 2006
@@ -1,9 +1,6 @@
package org.apache.ojb.odmg;
-import org.apache.ojb.broker.Identity;
-import org.odmg.Transaction;
-
-/* Copyright 2003-2004 The Apache Software Foundation
+/* Copyright 2003-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +15,9 @@
* limitations under the License.
*/
+import org.odmg.Transaction;
+import org.apache.ojb.broker.Identity;
+
/**
* Offers useful none odmg-standard methods of the odmg {@link org.odmg.Transaction} interface.
* <p>
@@ -90,7 +90,7 @@
* reference field while this transaction is in use.
*
* @param target The class to change cascading delete behavior of the references.
- * @param referenceField The field name of the 1:1, 1:n or 1:n reference.
+ * @param referenceField The field name of the 1:1, 1:n or m:n reference.
* @param doCascade If <em>true</em> cascading delete is enabled, <em>false</em> disabled.
*/
public void setCascadingDelete(Class target, String referenceField, boolean doCascade);
@@ -126,36 +126,36 @@
*/
public void setOrdering(boolean ordering);
- /**
- * Returns whether or not the persistent method calls determine
- * the persistent object order on commit.
- *
- * @see #setNoteUserOrder(boolean)
- */
- public boolean isNoteUserOrder();
-
- /**
- * If <em>true</em> the order of persisting method calls like
- * <br/> - {@link org.odmg.Transaction#lock(Object, int)}).
- * <br/> - {@link org.odmg.Database#deletePersistent(Object)}).
- * <br/> - {@link org.odmg.Database#makePersistent(Object)})
- * determine the order of objects before commit.
- * <br/>
- * If <em>false</em> the ordering was determined by OJB's internal
- * method calls and user calls.
- * <br/>
- * However it's possible to set this value as a global property
- * for all transactions using {@link ImplementationExt#setNoteUserOrder(boolean)}.
- * <p/>
- * <strong>NOTE:</strong> If OJB's ordering algorithm (see
- * {@link #setOrdering(boolean)}) is enabled, the
- * order of objects may change on commit.
- *
- * @param noteUserOrder If <em>true</em> the order of persisting
- * method calls determine the order of objects.
- * @see ImplementationExt#setNoteUserOrder(boolean)
- */
- public void setNoteUserOrder(boolean noteUserOrder);
+// /**
+// * Returns whether or not the persistent method calls determine
+// * the persistent object order on commit.
+// *
+// * @see #setNoteUserOrder(boolean)
+// */
+// public boolean isNoteUserOrder();
+//
+// /**
+// * If <em>true</em> the order of persisting method calls like
+// * <br/> - {@link org.odmg.Transaction#lock(Object, int)}).
+// * <br/> - {@link org.odmg.Database#deletePersistent(Object)}).
+// * <br/> - {@link org.odmg.Database#makePersistent(Object)})
+// * determine the order of objects before commit.
+// * <br/>
+// * If <em>false</em> the ordering was determined by OJB's internal
+// * method calls and user calls.
+// * <br/>
+// * However it's possible to set this value as a global property
+// * for all transactions using {@link ImplementationExt#setNoteUserOrder(boolean)}.
+// * <p/>
+// * <strong>NOTE:</strong> If OJB's ordering algorithm (see
+// * {@link #setOrdering(boolean)}) is enabled, the
+// * order of objects may change on commit.
+// *
+// * @param noteUserOrder If <em>true</em> the order of persisting
+// * method calls determine the order of objects.
+// * @see ImplementationExt#setNoteUserOrder(boolean)
+// */
+// public void setNoteUserOrder(boolean noteUserOrder);
/**
* Checks if the object with the given {@link org.apache.ojb.broker.Identity}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org