/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.ha.server.session;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.events.shared.RegisteredTriggerManager;
import org.hyperic.hq.ha.HAService;
import org.hyperic.hq.measurement.MeasurementConstants;
import org.hyperic.hq.measurement.server.session.AvailabilityCheckService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.MethodInvokingRunnable;
import org.springframework.stereotype.Service;
/**
* Implementation of {@link HAService} that gets started if we are in the .org
* HQ (HA not available) or by the master node of an HQ EE cluster
* implementation
* @author jhickey
*
*/
@Service("haService")
public class HAServiceImpl implements HAService {
private final Log log = LogFactory.getLog(HAServiceImpl.class);
private TaskScheduler scheduler;
private AvailabilityCheckService availabilityCheckService;
private ScheduledFuture<?> backfillTask;
private RegisteredTriggerManager registeredTriggerManager;
private final AtomicBoolean triggersHaveInitialized = new AtomicBoolean(false);
private final Thread triggerInitThread = new Thread() {
public void run() {
final long start = System.currentTimeMillis();
registeredTriggerManager.initializeTriggers();
final long finish = System.currentTimeMillis();
triggersHaveInitialized.set(true);
float elapsed = (finish-start)/1000/60;
log.info("Trigger initialization completed in " + elapsed + " minutes");
//Schedule backfill after triggers have been initialized
if (backfillTask == null) {
MethodInvokingRunnable backfill = new MethodInvokingRunnable();
backfill.setTargetObject(availabilityCheckService);
backfill.setTargetMethod("backfillPlatformAvailability");
try {
backfill.prepare();
final long twoMins = 2 * MeasurementConstants.MINUTE;
backfillTask = scheduler.scheduleWithFixedDelay(backfill, new Date(System.currentTimeMillis()+twoMins), twoMins);
} catch (Exception e) {
log.error("Unable to schedule availability backfill.", e);
}
}
}
};
@Autowired
public HAServiceImpl(@Value("#{scheduler}")TaskScheduler scheduler,
AvailabilityCheckService availabilityCheckService,
RegisteredTriggerManager registeredTriggerManager) {
this.scheduler = scheduler;
this.availabilityCheckService = availabilityCheckService;
this.registeredTriggerManager = registeredTriggerManager;
}
/**
* These services can only run on a master node when HA is used, so they
* have to be started programmatically once we know if HA is enabled
*/
public void start() {
triggerInitThread.start();
}
public boolean alertTriggersHaveInitialized() {
return triggersHaveInitialized.get();
}
public boolean isMasterNode() {
// HA not implemented in .org
return true;
}
public void stop() {
if (backfillTask != null) {
backfillTask.cancel(false);
this.backfillTask = null;
}
}
}