2 commits - java/code java/spacewalk-java.spec rel-eng/packages

StephenHerr sherr at fedoraproject.org
Tue Jun 26 18:46:34 UTC 2012


 java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataAction.java   |    1 
 java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataEvent.java    |   13 +
 java/code/src/com/redhat/rhn/frontend/xmlrpc/errata/ErrataHandler.java   |   27 ---
 java/code/src/com/redhat/rhn/manager/errata/AsyncErrataCloneCounter.java |   74 ++++++++++
 java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java           |   12 +
 java/spacewalk-java.spec                                                 |    5 
 rel-eng/packages/spacewalk-java                                          |    2 
 7 files changed, 110 insertions(+), 24 deletions(-)

New commits:
commit 2de3ceb59ad5116cf6bab7c09724cb3552406c36
Author: Stephen Herr <sherr at redhat.com>
Date:   Tue Jun 26 14:46:23 2012 -0400

    Automatic commit of package [spacewalk-java] release [1.8.98-1].

diff --git a/java/spacewalk-java.spec b/java/spacewalk-java.spec
index dd8204c..2b65ffe 100644
--- a/java/spacewalk-java.spec
+++ b/java/spacewalk-java.spec
@@ -23,7 +23,7 @@ Name: spacewalk-java
 Summary: Spacewalk Java site packages
 Group: Applications/Internet
 License: GPLv2
-Version: 1.8.97
+Version: 1.8.98
 Release: 1%{?dist}
 URL:       https://fedorahosted.org/spacewalk
 Source0:   https://fedorahosted.org/releases/s/p/spacewalk/%{name}-%{version}.tar.gz 
@@ -615,6 +615,9 @@ fi
 %{jardir}/postgresql-jdbc.jar
 
 %changelog
+* Tue Jun 26 2012 Stephen Herr <sherr at redhat.com> 1.8.98-1
+- 829485 - resolveing potential deadlock during asynchronous errata clone
+
 * Tue Jun 26 2012 Jan Pazdziora 1.8.97-1
 - Each dataset must have a different name.
 - Add CSV downloader for scap search page.
diff --git a/rel-eng/packages/spacewalk-java b/rel-eng/packages/spacewalk-java
index a6ddb83..5b9f9ed 100644
--- a/rel-eng/packages/spacewalk-java
+++ b/rel-eng/packages/spacewalk-java
@@ -1 +1 @@
-1.8.97-1 java/
+1.8.98-1 java/


commit 7713d370ccb509980056ecd18a5846960f964458
Author: Stephen Herr <sherr at redhat.com>
Date:   Tue Jun 26 14:46:08 2012 -0400

    829485 - resolveing potential deadlock during asynchronous errata clone

diff --git a/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataAction.java b/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataAction.java
index 74a64a5..d2db2ea 100644
--- a/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataAction.java
@@ -43,5 +43,6 @@ extends AbstractDatabaseAction {
         errata.add(ErrataFactory.lookupById(eid));
         ErrataManager.cloneErrataApi(msg.getChan(), errata,
                 msg.getUser(), msg.isInheritPackages());
+        msg.deregister();
     }
 }
diff --git a/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataEvent.java b/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataEvent.java
index 458d126..7b8f173 100644
--- a/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataEvent.java
+++ b/java/code/src/com/redhat/rhn/frontend/events/NewCloneErrataEvent.java
@@ -20,6 +20,7 @@ import com.redhat.rhn.domain.channel.Channel;
 import com.redhat.rhn.domain.channel.ChannelFactory;
 import com.redhat.rhn.domain.user.User;
 import com.redhat.rhn.domain.user.UserFactory;
+import com.redhat.rhn.manager.errata.AsyncErrataCloneCounter;
 
 import org.hibernate.Transaction;
 
@@ -128,5 +129,17 @@ public class NewCloneErrataEvent implements EventDatabaseMessage {
         return UserFactory.lookupById(userId);
     }
 
+    /**
+     * Register the async clone event with the counter
+     */
+    public void register() {
+        AsyncErrataCloneCounter.getInstance().addAsyncErrataCloneJob(chanId);
+    }
 
+    /**
+     * De-regiser the async clone event from the counter
+     */
+    public void deregister() {
+        AsyncErrataCloneCounter.getInstance().removeAsyncErrataCloneJob(chanId);
+    }
 }
diff --git a/java/code/src/com/redhat/rhn/frontend/xmlrpc/errata/ErrataHandler.java b/java/code/src/com/redhat/rhn/frontend/xmlrpc/errata/ErrataHandler.java
index d557ee7..49aca00 100644
--- a/java/code/src/com/redhat/rhn/frontend/xmlrpc/errata/ErrataHandler.java
+++ b/java/code/src/com/redhat/rhn/frontend/xmlrpc/errata/ErrataHandler.java
@@ -865,11 +865,6 @@ public class ErrataHandler extends BaseHandler {
      *
      * @xmlrpc.doc Clone a list of errata into the specified channel.
      *
-     * Warning: Issuing a synchronous clone request for a channel that has asynchronous
-     * errata cloning jobs pending can result in a database deadlock! Adding more
-     * asynchronous jobs is safe. If deadlock occurs one must re-schedule both the
-     * synchronous and asynchronous jobs to ensure all errata are cloned.
-     *
      * @xmlrpc.param #session_key()
      * @xmlrpc.param #param("string", "channel_label")
      * @xmlrpc.param
@@ -896,11 +891,6 @@ public class ErrataHandler extends BaseHandler {
      *
      * @xmlrpc.doc Asynchronously clone a list of errata into the specified channel.
      *
-     * Warning: Issuing a synchronous clone request for a channel that has asynchronous
-     * errata cloning jobs pending can result in a database deadlock! Adding more
-     * asynchronous jobs is safe. If deadlock occurs one must re-schedule both the
-     * synchronous and asynchronous jobs to ensure all errata are cloned.
-     *
      * @xmlrpc.param #session_key()
      * @xmlrpc.param #param("string", "channel_label")
      * @xmlrpc.param
@@ -968,6 +958,13 @@ public class ErrataHandler extends BaseHandler {
                     inheritPackages);
             return new ArrayList<Errata>().toArray();
         }
+        else if (ErrataManager.channelHasPendingAsyncCloneJobs(channel)) {
+            throw new InvalidChannelException(
+                    "Channel " +
+                            channel.getLabel() +
+                            " has pending asynchronous errata clone jobs. You must wait" +
+                    "until asychronous errata clone jobs are done.");
+        }
         return ErrataManager.cloneErrataApi(channel, errataToClone,
                 loggedInUser, inheritPackages);
     }
@@ -987,11 +984,6 @@ public class ErrataHandler extends BaseHandler {
      * @xmlrpc.doc Clones a list of errata into a specified cloned channel
      * according the original erratas.
      *
-     * Warning: Issuing a synchronous cloneAsOriginal request for a channel that has
-     * asynchronous errata cloning jobs pending can result in a database deadlock! Adding
-     * more asynchronous jobs is safe. If deadlock occurs one must re-schedule both the
-     * synchronous and asynchronous jobs to ensure all errata are cloned.
-     *
      * @xmlrpc.param #session_key()
      * @xmlrpc.param #param("string", "channel_label")
      * @xmlrpc.param
@@ -1020,11 +1012,6 @@ public class ErrataHandler extends BaseHandler {
      * @xmlrpc.doc Asynchronously clones a list of errata into a specified cloned channel
      * according the original erratas
      *
-     * Warning: Issuing a synchronous cloneAsOriginal request for a channel that has
-     * asynchronous errata cloning jobs pending can result in a database deadlock! Adding
-     * more asynchronous jobs is safe. If deadlock occurs one must re-schedule both the
-     * synchronous and asynchronous jobs to ensure all errata are cloned.
-     *
      * @xmlrpc.param #session_key()
      * @xmlrpc.param #param("string", "channel_label")
      * @xmlrpc.param
diff --git a/java/code/src/com/redhat/rhn/manager/errata/AsyncErrataCloneCounter.java b/java/code/src/com/redhat/rhn/manager/errata/AsyncErrataCloneCounter.java
new file mode 100644
index 0000000..ed3d528
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/manager/errata/AsyncErrataCloneCounter.java
@@ -0,0 +1,74 @@
+package com.redhat.rhn.manager.errata;
+
+import java.util.Hashtable;
+
+/**
+ * If someone attempts to schedule a synchronous errata clone into a
+ * channel that has asynchronous errata clones taking place in the
+ * background, a database deadlock will occur. There is no way to
+ * avoid the deadlock, so instead we'll keep track of how many
+ * pending jobs we have here. The jobs themselves are not persistent,
+ * residing in tomcat memory only, so the counter should not be
+ * persistent. That is why I implemented the counter as a singeton
+ * class instead of a database table or some other such implementation.
+ * 
+ * @author Stephen Herr <sherr at redhat.com>
+ *
+ */
+public class AsyncErrataCloneCounter {
+    // hashtable is syncronized, so is threadsafe
+    private final Hashtable<Long, Integer> count;
+    private static AsyncErrataCloneCounter instance = new AsyncErrataCloneCounter();
+
+    private AsyncErrataCloneCounter() {
+        count = new Hashtable<Long, Integer>();
+    }
+
+    /**
+     * Get the one and only instance of AsyncErrataCloneCounter
+     * @return the singleton instance
+     */
+    public static AsyncErrataCloneCounter getInstance() {
+        return instance;
+    }
+
+    /**
+     * Check if a channel has pending asyncrhonous errata clone jobs
+     * @param cid channel id
+     * @return True if there are pending jobs for a channel, false otherwise
+     */
+    public boolean channelHasPendingJobs(Long cid) {
+        Integer n = count.get(cid);
+        if (n == null || n == 0) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Call this with the channel id when scheduling a new asyncronous
+     * errata clone job
+     * @param cid channel id
+     */
+    public void addAsyncErrataCloneJob(Long cid) {
+        Integer n = count.get(cid);
+        if (n != null) {
+            count.put(cid, n + 1);
+        }
+        else {
+            count.put(cid, 1);
+        }
+    }
+
+    /**
+     * Call this with channel id when completeing an asynchronous
+     * errata clone job
+     * @param cid channel id
+     */
+    public void removeAsyncErrataCloneJob(Long cid) {
+        Integer n = count.get(cid);
+        if (n != null && n > 0) {
+            count.put(cid, n - 1);
+        }
+    }
+}
diff --git a/java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java b/java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java
index 3e3f5c8..4ee5a65 100644
--- a/java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java
+++ b/java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java
@@ -1274,12 +1274,20 @@ public class ErrataManager extends BaseManager {
         for (long eid : errata) {
             NewCloneErrataEvent neve = new NewCloneErrataEvent(chan, eid, user,
                     inheritPackages);
+            neve.register();
             MessageQueue.publish(neve);
         }
     }
 
-
-
+    /**
+     * Check if the channel has pending asynchronous errata clone jobs
+     * @param channel channel to check
+     * @return true if there are pending jobs, false otherwise
+     */
+    public static boolean channelHasPendingAsyncCloneJobs(Channel channel) {
+        return AsyncErrataCloneCounter.getInstance().channelHasPendingJobs(
+                channel.getId());
+    }
 
     /**
      * Send errata notifications for a particular errata and channel




More information about the spacewalk-commits mailing list