/* * RHQ Management Platform * Copyright (C) 2005-2008 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.server.configuration.job; import java.util.List; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.util.OrderingField; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageOrdering; import org.rhq.core.util.exception.ThrowableUtil; import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal; import org.rhq.enterprise.server.util.LookupUtil; public abstract class AbstractGroupConfigurationUpdateJob implements Job { public static final String DATAMAP_INT_CONFIG_GROUP_UPDATE_ID = "configGroupUpdateId"; public static final String DATAMAP_INT_SUBJECT_ID = "subjectId"; protected static JobDetail getJobDetail(ResourceGroup group, Subject subject, JobDataMap jobDataMap, Class jobClass, String jobNamePrefix) { JobDetail jobDetail = new JobDetail(); jobDetail.setName(createUniqueJobName(group, subject, jobNamePrefix)); jobDetail.setGroup(createJobGroupName(group, jobNamePrefix)); jobDetail.setVolatility(false); // we want it persisted jobDetail.setDurability(false); jobDetail.setRequestsRecovery(false); jobDetail.setJobClass(jobClass); jobDetail.setJobDataMap(jobDataMap); return jobDetail; } public void execute(JobExecutionContext jobContext) throws JobExecutionException { JobDetail jobDetail = jobContext.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); Integer configurationGroupUpdateId = jobDataMap.getIntFromString(DATAMAP_INT_CONFIG_GROUP_UPDATE_ID); Integer subjectId = jobDataMap.getIntFromString(DATAMAP_INT_SUBJECT_ID); Subject subject = LookupUtil.getSubjectManager().getSubjectById(subjectId); processGroupConfigurationUpdate(configurationGroupUpdateId, subject); } private void processGroupConfigurationUpdate(Integer groupConfigurationUpdateId, Subject subject) { ConfigurationManagerLocal configurationManager = LookupUtil.getConfigurationManager(); String errorMessages = null; try { long childPluginConfigurationUpdateCount = getConfigurationUpdateCount(groupConfigurationUpdateId, configurationManager); int rowsProcessed = 0; PageControl pc = new PageControl(0, 1000, new OrderingField("cu.id", PageOrdering.ASC)); while (true) { List<Integer> pagedChildUpdateIds = getConfigurationUpdateIds(groupConfigurationUpdateId, configurationManager, pc); if (pagedChildUpdateIds.size() <= 0) { break; } for (Integer childUpdateId : pagedChildUpdateIds) { // failing one update request is not reason to fail all of the remaining updates // so, wrap in a try catch and gather up the errors to subsequently fail the group update. This // will especially benefit group plugin config, which currently executes synchronously. try { executeConfigurationUpdate(configurationManager, childUpdateId, subject); } catch (Exception e) { errorMessages = appendErrorMessages(errorMessages, "Failed Member Update Id=" + childUpdateId, e.toString()); } } rowsProcessed += pagedChildUpdateIds.size(); if (rowsProcessed >= childPluginConfigurationUpdateCount) { break; } pc.setPageNumber(pc.getPageNumber() + 1); } } catch (Exception e) { errorMessages = appendErrorMessages(errorMessages, "Failed Group Update Id=" + groupConfigurationUpdateId, ThrowableUtil.getAllMessages(e)); } finally { completeGroupConfigurationUpdate(configurationManager, groupConfigurationUpdateId, errorMessages); } } private String appendErrorMessages(String currentMessages, String header, String newMessages) { currentMessages = (null == currentMessages) ? "" : currentMessages + "\n"; return currentMessages.concat(" [" + header + ": " + newMessages); } private static String createUniqueJobName(ResourceGroup group, Subject subject, String jobNamePrefix) { return createJobGroupName(group, jobNamePrefix) + "-" + subject.getName().hashCode() + "-" + System.currentTimeMillis(); } private static String createJobGroupName(ResourceGroup group, String jobNamePrefix) { return jobNamePrefix + group.getId(); } protected abstract List<Integer> getConfigurationUpdateIds(Integer groupPluginConfigurationUpdateId, ConfigurationManagerLocal configurationManager, PageControl pc); protected abstract long getConfigurationUpdateCount(Integer groupPluginConfigurationUpdateId, ConfigurationManagerLocal configurationManager); protected abstract void executeConfigurationUpdate(ConfigurationManagerLocal configurationManager, Integer childUpdateId, Subject subject); protected abstract void completeGroupConfigurationUpdate(ConfigurationManagerLocal configurationManager, Integer groupConfigurationUpdateId, String errorMessages); }