/**
* Copyright (c) 2009--2015 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
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.taskomatic.task.repomd;
import com.redhat.rhn.common.conf.Config;
import com.redhat.rhn.common.conf.ConfigDefaults;
import com.redhat.rhn.common.db.datasource.ModeFactory;
import com.redhat.rhn.common.db.datasource.SelectMode;
import com.redhat.rhn.common.db.datasource.WriteMode;
import com.redhat.rhn.common.hibernate.HibernateFactory;
import com.redhat.rhn.domain.channel.Channel;
import com.redhat.rhn.domain.channel.ChannelFactory;
import com.redhat.rhn.taskomatic.task.TaskConstants;
import com.redhat.rhn.taskomatic.task.threaded.QueueWorker;
import com.redhat.rhn.taskomatic.task.threaded.TaskQueue;
import org.apache.log4j.Logger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @version $Rev $
*
*/
public class ChannelRepodataWorker implements QueueWorker {
private RepositoryWriter repoWriter;
private TaskQueue parentQueue;
private Logger logger;
private String channelLabelToProcess;
private List queueEntries;
/**
*
* @param workItem work item map
* @param parentLogger repomd logger
*/
public ChannelRepodataWorker(Map workItem, Logger parentLogger) {
logger = parentLogger;
String prefixPath = Config.get().getString(ConfigDefaults.REPOMD_PATH_PREFIX,
"rhn/repodata");
String mountPoint =
Config.get().getString(ConfigDefaults.REPOMD_CACHE_MOUNT_POINT, "/pub");
channelLabelToProcess = (String) workItem.get("channel_label");
// We need to find out whether to use Rpm or Debian repository
Channel channelToProcess = ChannelFactory.lookupByLabel(channelLabelToProcess);
// if the channelExists in the db still
if (channelToProcess != null && channelToProcess.getChannelArch()
.getArchType().getLabel().equalsIgnoreCase("deb")) {
repoWriter = new DebRepositoryWriter(prefixPath, mountPoint);
}
else {
repoWriter = new RpmRepositoryWriter(prefixPath, mountPoint);
}
logger.debug("Creating ChannelRepodataWorker with prefixPath(" + prefixPath +
"), mountPoint(" + mountPoint + ")" + " for channel_label (" +
channelLabelToProcess + ")");
}
/**
* Sets the parent queue
* @param queue task queue
*/
public void setParentQueue(TaskQueue queue) {
parentQueue = queue;
}
/**
* runner method to process the parentQueue
*/
public void run() {
try {
parentQueue.workerStarting();
if (!isChannelLabelAlreadyInProcess()) {
markInProgress(true);
populateQueueEntryDetails();
Channel channelToProcess = ChannelFactory
.lookupByLabel(channelLabelToProcess);
// if the channelExists in the db still
if (channelToProcess != null) {
// see if the channel is stale, or one of the entries has
// force='Y'
if (queueContainsBypass("force") ||
repoWriter.isChannelRepodataStale(channelToProcess)) {
if (queueContainsBypass("bypass_filters") ||
channelToProcess.isChannelRepodataRequired()) {
repoWriter.writeRepomdFiles(channelToProcess);
}
}
else {
logger.debug("Not processing channel(" + channelLabelToProcess +
") because the request isn't forced AND the channel repodata " +
"isn't stale");
}
}
else {
repoWriter.deleteRepomdFiles(channelLabelToProcess, true);
}
dequeueChannel();
HibernateFactory.commitTransaction();
}
else {
HibernateFactory.commitTransaction();
logger.warn("NOT processing channel(" + channelLabelToProcess +
") because another thread is already working on run");
}
}
catch (Exception e) {
logger.error(e);
e.printStackTrace();
parentQueue.getQueueRun().failed();
// unmark channel to be worked on
markInProgress(false);
parentQueue.changeRun(null);
}
finally {
parentQueue.workerDone();
HibernateFactory.closeSession();
}
}
/**
* populates the queue details for repomd event
*/
private void populateQueueEntryDetails() {
SelectMode selector = ModeFactory.getMode(TaskConstants.MODE_NAME,
TaskConstants.TASK_QUERY_REPOMD_DETAILS_QUERY);
Map<String, Object> params = new HashMap<String, Object>();
params.put("channel_label", channelLabelToProcess);
queueEntries = selector.execute(params);
}
/**
*
* @return Returns the progress status of the channel
*/
private boolean isChannelLabelAlreadyInProcess() {
SelectMode selector = ModeFactory.getMode(TaskConstants.MODE_NAME,
TaskConstants.TASK_QUERY_REPOMD_DETAILS_QUERY);
Map<String, Object> params = new HashMap<String, Object>();
params.put("channel_label", channelLabelToProcess);
return (selector.execute(params).size() > 0);
}
/**
*
* @param entryToCheck
* @return Returns a boolean to force or not
*/
private boolean queueContainsBypass(String entryToCheck) {
boolean shouldForce = false;
for (Object currentEntry : queueEntries) {
String forceFlag = (String) ((Map) currentEntry).get(entryToCheck);
if ("Y".equalsIgnoreCase(forceFlag)) {
shouldForce = true;
}
}
return shouldForce;
}
/**
* marks the channel as in progress to avoid conflicts
*/
private void markInProgress(boolean inProgress) {
WriteMode inProgressChannel;
if (inProgress) {
inProgressChannel = ModeFactory.getWriteMode(TaskConstants.MODE_NAME,
TaskConstants.TASK_QUERY_REPOMD_MARK_IN_PROGRESS);
}
else {
inProgressChannel = ModeFactory.getWriteMode(TaskConstants.MODE_NAME,
TaskConstants.TASK_QUERY_REPOMD_UNMARK_IN_PROGRESS);
}
Map<String, String> dqeParams = new HashMap<String, String>();
dqeParams.put("channel_label", channelLabelToProcess);
try {
int channelLabels = inProgressChannel.executeUpdate(dqeParams);
if (logger.isDebugEnabled()) {
if (inProgress) {
logger.debug("Marked " + channelLabels + " rows from the " +
"rhnRepoRegenQueue table in progress by " +
"setting next_action to null");
}
else {
logger.debug("Cleared " + channelLabels + " in progress rows " +
"from the rhnRepoRegenQueue table by setting next_action");
}
}
HibernateFactory.commitTransaction();
}
catch (Exception e) {
logger.error(
"Error un/marking in use for channel_label: " + channelLabelToProcess,
e);
HibernateFactory.rollbackTransaction();
}
finally {
HibernateFactory.closeSession();
}
}
/**
* dequeue the queued channel for repomd generation
*/
private void dequeueChannel() throws Exception {
WriteMode deqChannel = ModeFactory.getWriteMode(TaskConstants.MODE_NAME,
TaskConstants.TASK_QUERY_REPOMD_DEQUEUE);
Map<String, String> dqeParams = new HashMap<String, String>();
dqeParams.put("channel_label", channelLabelToProcess);
try {
int eqDeleted = deqChannel.executeUpdate(dqeParams);
if (logger.isDebugEnabled()) {
logger.debug("deleted " + eqDeleted +
" rows from the rhnRepoRegenQueue table");
}
HibernateFactory.commitTransaction();
}
catch (Exception e) {
logger.error("Error removing Channel from queue for Channel: " +
channelLabelToProcess, e);
HibernateFactory.rollbackTransaction();
return;
}
finally {
HibernateFactory.closeSession();
}
}
}