java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java | 35 +++++++++-
java/code/src/com/redhat/rhn/domain/channel/ChannelFactory.java | 10 ++
java/code/src/com/redhat/rhn/manager/channel/ChannelEditor.java | 3
java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java | 1
4 files changed, 46 insertions(+), 3 deletions(-)
New commits:
commit bded6355c0ef72f980cbedac7ede350bf6b81fc6
Author: Milan Zazrivec <mzazrivec(a)redhat.com>
Date: Wed Jan 22 16:38:24 2014 +0100
1053591 - fix deadlock when cloning using spacewalk-clone-by-date
We need to explicitly lock one row of rhnChannel table to avoid
a db deadlock.
diff --git a/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java
b/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java
index 8d1fcc2..502b995 100644
--- a/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java
+++ b/java/code/src/com/redhat/rhn/common/hibernate/HibernateFactory.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2009--2012 Red Hat, Inc.
+ * Copyright (c) 2009--2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -25,9 +25,11 @@ import org.apache.log4j.Logger;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.Session;
+import org.hibernate.Version;
import org.hibernate.metadata.ClassMetadata;
import java.io.ByteArrayOutputStream;
@@ -385,6 +387,37 @@ public abstract class HibernateFactory {
}
/**
+ * Return a locked persistent instance of the given entity class with
+ * the given identifier, or null if there is no such persistent instance.
+ * (If the instance, or a proxy for the instance, is already associated
+ * with the session, return that instance or proxy.)
+ * @param clazz a persistent class
+ * @param id an identifier
+ * @return Object persistent instance or null
+ */
+ protected Object lockObject(Class clazz, Serializable id) {
+ Object retval = null;
+ Session session = null;
+
+ try {
+ session = HibernateFactory.getSession();
+ String hVersion = HibernateFactory.getHibernateVersion().substring(0, 3);
+
+ retval = session.get(clazz, id, LockMode.UPGRADE);
+ }
+ catch (MappingException me) {
+ getLogger().error("Mapping not found for " + clazz.getName(), me);
+
+ }
+ catch (HibernateException he) {
+ getLogger().error("Hibernate exception: " + he.toString());
+ }
+
+ return retval;
+ }
+
+
+ /**
* Util to reload an object using Hibernate
* @param obj to be reloaded
* @return Object found if not, null
diff --git a/java/code/src/com/redhat/rhn/domain/channel/ChannelFactory.java
b/java/code/src/com/redhat/rhn/domain/channel/ChannelFactory.java
index 1689ac3..0116382 100644
--- a/java/code/src/com/redhat/rhn/domain/channel/ChannelFactory.java
+++ b/java/code/src/com/redhat/rhn/domain/channel/ChannelFactory.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2009--2012 Red Hat, Inc.
+ * Copyright (c) 2009--2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -1179,4 +1179,12 @@ public class ChannelFactory extends HibernateFactory {
}
return ids;
}
+
+ /*
+ * Locks the given Channel for update on a database level
+ * @param c Channel to lock
+ */
+ public static void lock(Channel c) {
+ singleton.lockObject(Channel.class, c.getId());
+ }
}
diff --git a/java/code/src/com/redhat/rhn/manager/channel/ChannelEditor.java
b/java/code/src/com/redhat/rhn/manager/channel/ChannelEditor.java
index 90766c6..51036c7 100644
--- a/java/code/src/com/redhat/rhn/manager/channel/ChannelEditor.java
+++ b/java/code/src/com/redhat/rhn/manager/channel/ChannelEditor.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2009--2012 Red Hat, Inc.
+ * Copyright (c) 2009--2014 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -58,6 +58,7 @@ public class ChannelEditor {
* @param packageIds A list containing the ids of packages to add.
*/
public void addPackages(User user, Channel channel, Collection packageIds) {
+ ChannelFactory.lock(channel);
changePackages(user, channel, packageIds, true);
}
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 18d9412..59e75ed 100644
--- a/java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java
+++ b/java/code/src/com/redhat/rhn/manager/errata/ErrataManager.java
@@ -1338,6 +1338,7 @@ public class ErrataManager extends BaseManager {
public static void cloneErrataApiAsync(Channel chan, List<Long> errata,
User user, boolean inheritPackages) {
Logger.getLogger(ErrataManager.class).debug("Cloning");
+ ChannelFactory.lock(chan);
for (long eid : errata) {
NewCloneErrataEvent neve = new NewCloneErrataEvent(chan, eid, user,
inheritPackages);