openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From p..@apache.org
Subject svn commit: r552059 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/datacache/ openjpa-kernel/src/main/java/org/apache/openjpa/event/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/
Date Fri, 29 Jun 2007 23:08:42 GMT
Author: pcl
Date: Fri Jun 29 16:08:41 2007
New Revision: 552059

URL: http://svn.apache.org/viewvc?view=rev&rev=552059
Log:
OPENJPA-70. Added new RemoteCommitEvent payload type and logic to fire RemoteCommitEvents
when stale records are detected. This logic still gets fired via afterCommit(), even though
these checks can happen either after a commit or a flush is issued. Additionally, these events
are only fired against local listeners, so actually represent local analysis that is detecting
remote events, rather than remote events themselves.

Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEvent.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheOptimisticLockRecovery.java

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java?view=diff&rev=552059&r1=552058&r2=552059
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
Fri Jun 29 16:08:41 2007
@@ -513,7 +513,7 @@
             for (Iterator iter = exceps.iterator(); iter.hasNext(); ) {
                 Exception e = (Exception) iter.next();
                 if (e instanceof OptimisticException)
-                    evictOptimisticLockFailure((OptimisticException) e);
+                    notifyOptimisticLockFailure((OptimisticException) e);
             }
             return exceps;
         }
@@ -552,22 +552,25 @@
     }
 
     /**
-     * Evict from the cache the OID (if available) that resulted in an
-     * optimistic lock exception iff the version information in the cache 
-     * matches the version information in the state manager for the failed
-     * instance. This means that we will evict data from the cache for records 
-     * that should have successfully committed according to the data cache but 
+     * Fire local staleness detection events from the cache the OID (if
+     * available) that resulted in an optimistic lock exception iff the
+     * version information in the cache matches the version information
+     * in the state manager for the failed instance. This means that we
+     * will evict data from the cache for records that should have
+     * successfully committed according to the data cache but
      * did not. The only predictable reason that could cause this behavior
      * is a concurrent out-of-band modification to the database that was not 
      * communicated to the cache. This logic makes OpenJPA's data cache 
      * somewhat tolerant of such behavior, in that the cache will be cleaned 
      * up as failures occur.
      */
-    private void evictOptimisticLockFailure(OptimisticException e) {
-        Object o = ((OptimisticException) e).getFailedObject();
+    private void notifyOptimisticLockFailure(OptimisticException e) {
+        Object o = e.getFailedObject();
         OpenJPAStateManager sm = _ctx.getStateManager(o);
         if (sm == null)
             return;
+        Object oid = sm.getId();
+        boolean remove;
 
         // this logic could be more efficient -- we could aggregate
         // all the cache->oid changes, and then use DataCache.removeAll() 
@@ -579,11 +582,10 @@
 
         cache.writeLock();
         try {
-            DataCachePCData data = cache.get(sm.getId());
+            DataCachePCData data = cache.get(oid);
             if (data == null)
                 return;
 
-            boolean remove;
             switch (compareVersion(sm, sm.getVersion(), data.getVersion())) {
                 case StoreManager.VERSION_LATER:
                 case StoreManager.VERSION_SAME:
@@ -614,10 +616,17 @@
                     break;
             }
             if (remove)
+                // remove directly instead of via the RemoteCommitListener
+                // since we have a write lock here already, so this is more
+                // efficient than read-locking and then write-locking later.
                 cache.remove(sm.getId());
         } finally {
             cache.writeUnlock();
         }
+
+        // fire off a remote commit stalenesss detection event.
+        _ctx.getConfiguration().getRemoteCommitEventManager()
+            .fireLocalStaleNotification(oid);
     }
 
     public StoreQuery newQuery(String language) {

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEvent.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEvent.java?view=diff&rev=552059&r1=552058&r2=552059
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEvent.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEvent.java
Fri Jun 29 16:08:41 2007
@@ -40,12 +40,12 @@
     implements Externalizable {
 
     /**
-     * Names of added classes, upated and deleted Object IDs.
+     * Names of added classes, updated and deleted Object IDs.
      */
     public static final int PAYLOAD_OIDS = 0;
 
     /**
-     * Names of added classes, added, upated and deleted Object IDs.
+     * Names of added classes, added, updated and deleted Object IDs.
      */
     public static final int PAYLOAD_OIDS_WITH_ADDS = 1;
 
@@ -54,6 +54,16 @@
      */
     public static final int PAYLOAD_EXTENTS = 2;
 
+    /**
+     * The local {@link BrokerFactory} detected that local data is out of date
+     * with the data store. Stale object IDs will be in t he updated set,
+     * although it is possible that records were actually deleted, rather than
+     * updated.
+     *
+     * @since 1.0.0
+     */
+    public static final int PAYLOAD_LOCAL_STALE_DETECTION = 3;
+
     private static final Localizer s_loc = Localizer.forPackage
         (RemoteCommitEvent.class);
 
@@ -114,7 +124,9 @@
 
     /**
      * When the event type is not PAYLOAD_EXTENTS, return the set of
-     * object IDs for updated objects.
+     * object IDs for updated objects. When the event type is
+     * PAYLOAD_LOCAL_STALE_DETECTION, items in this list may actually have
+     * been deleted from the database.
      */
     public Collection getUpdatedObjectIds() {
         if (_payload == PAYLOAD_EXTENTS)

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.java?view=diff&rev=552059&r1=552058&r2=552059
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/event/RemoteCommitEventManager.java
Fri Jun 29 16:08:41 2007
@@ -23,6 +23,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Collections;
 
 import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.kernel.Broker;
@@ -114,6 +115,17 @@
         RemoteCommitListener listen = (RemoteCommitListener) listener;
         RemoteCommitEvent ev = (RemoteCommitEvent) event;
         listen.afterCommit(ev);
+    }
+
+    /**
+     * Fire an event to local listeners only notifying them of a detected
+     * stale record.
+     */
+    public void fireLocalStaleNotification(Object oid) {
+        RemoteCommitEvent ev = new RemoteCommitEvent(
+            RemoteCommitEvent.PAYLOAD_LOCAL_STALE_DETECTION,
+            null, null, Collections.singleton(oid), null);
+        fireEvent(ev);
     }
 
     //////////////////////////////////////

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheOptimisticLockRecovery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheOptimisticLockRecovery.java?view=diff&rev=552059&r1=552058&r2=552059
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheOptimisticLockRecovery.java
(original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/TestDataCacheOptimisticLockRecovery.java
Fri Jun 29 16:08:41 2007
@@ -28,17 +28,36 @@
 
 import org.apache.openjpa.persistence.OpenJPAPersistence;
 import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+import org.apache.openjpa.event.RemoteCommitListener;
+import org.apache.openjpa.event.RemoteCommitEvent;
 
 public class TestDataCacheOptimisticLockRecovery
     extends SingleEMFTestCase {
 
     private int pk;
+    private int remoteCommitEventStaleCount = 0;
+    private Object staleOid;
 
     public void setUp() {
         setUp("openjpa.DataCache", "true",
             "openjpa.RemoteCommitProvider", "sjvm",
             OptimisticLockInstance.class);
 
+        emf.getConfiguration().getRemoteCommitEventManager().addListener(
+            new RemoteCommitListener() {
+                public void afterCommit(RemoteCommitEvent e) {
+                    if (e.getPayloadType() ==
+                        RemoteCommitEvent.PAYLOAD_LOCAL_STALE_DETECTION) {
+                        remoteCommitEventStaleCount++;
+                        staleOid = e.getUpdatedObjectIds().iterator().next();
+                    }
+                }
+
+                public void close() {
+                }
+            }
+        );
+
         EntityManager em = emf.createEntityManager();
         em.getTransaction().begin();
         OptimisticLockInstance oli = new OptimisticLockInstance("foo");
@@ -59,6 +78,9 @@
         em = emf.createEntityManager();
         em.getTransaction().begin();
         OptimisticLockInstance oli = em.find(OptimisticLockInstance.class, pk);
+        Object oid = OpenJPAPersistence.toOpenJPAObjectId(
+            OpenJPAPersistence.getMetaData(oli),
+            OpenJPAPersistence.cast(em).getObjectId(oli));
         int firstOpLockValue = oli.getOpLock();
         em.lock(oli, LockModeType.READ);
 
@@ -90,7 +112,11 @@
                 em.getTransaction().rollback();
         }
 
-        // 4. obtain the object in a new persistence context and
+        // 4. check that the corresponding remote commit event was fired
+        assertEquals(1, remoteCommitEventStaleCount);
+        assertEquals(oid, staleOid);
+
+        // 5. obtain the object in a new persistence context and
         // assert that the oplock column is set to the one that
         // happened in the out-of-band transaction
         em.close();
@@ -102,14 +128,13 @@
         assertEquals("data cache is not being cleared when oplock "
             + "violations occur", secondOpLockValue, oli.getOpLock());
 
-        // 5. get a read lock on the instance and commit the tx; this
+        // 6. get a read lock on the instance and commit the tx; this
         // time it should go through
         em.getTransaction().begin();
         em.lock(oli, LockModeType.READ);
         try {
             em.getTransaction().commit();
         } catch (RollbackException e) {
-            e.printStackTrace();
             throw e;
         } finally {
             if (em.getTransaction().isActive())



Mime
View raw message