/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) 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, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.poller.pollables; import java.net.InetAddress; import java.util.Date; import org.opennms.core.utils.ThreadCategory; import org.opennms.netmgt.EventConstants; import org.opennms.netmgt.model.PollStatus; import org.opennms.netmgt.poller.InetNetworkInterface; import org.opennms.netmgt.poller.MonitoredService; import org.opennms.netmgt.poller.NetworkInterface; import org.opennms.netmgt.scheduler.PostponeNecessary; import org.opennms.netmgt.scheduler.ReadyRunnable; import org.opennms.netmgt.scheduler.Schedule; import org.opennms.netmgt.xml.event.Event; /** * Represents a PollableService * * @author <a href="mailto:brozow@opennms.org">Mathew Brozowski</a> * @version $Id: $ */ public class PollableService extends PollableElement implements ReadyRunnable, MonitoredService { private final class PollRunner implements Runnable { private volatile PollStatus m_pollStatus; public void run() { doPoll(); getNode().processStatusChange(new Date()); m_pollStatus = getStatus(); } public PollStatus getPollStatus() { return m_pollStatus; } } private final String m_svcName; private final InetNetworkInterface m_netInterface; private volatile PollConfig m_pollConfig; private volatile PollStatus m_oldStatus; private volatile Schedule m_schedule; private volatile long m_statusChangeTime = 0L; /** * <p>Constructor for PollableService.</p> * * @param svcName a {@link java.lang.String} object. * @param iface a {@link org.opennms.netmgt.poller.pollables.PollableInterface} object. */ public PollableService(PollableInterface iface, String svcName) { super(iface, Scope.SERVICE); m_svcName = svcName; m_netInterface = new InetNetworkInterface(iface.getAddress()); } /** * <p>getInterface</p> * * @return a {@link org.opennms.netmgt.poller.pollables.PollableInterface} object. */ public PollableInterface getInterface() { return (PollableInterface)getParent(); } /** * <p>getNode</p> * * @return a {@link org.opennms.netmgt.poller.pollables.PollableNode} object. */ public PollableNode getNode() { return getInterface().getNode(); } /** * <p>getNetwork</p> * * @return a {@link org.opennms.netmgt.poller.pollables.PollableNetwork} object. */ public PollableNetwork getNetwork() { return getInterface().getNetwork(); } /** * <p>getContext</p> * * @return a {@link org.opennms.netmgt.poller.pollables.PollContext} object. */ public PollContext getContext() { return getInterface().getContext(); } /** * <p>getSvcName</p> * * @return a {@link java.lang.String} object. */ public String getSvcName() { return m_svcName; } /** * <p>getIpAddr</p> * * @return a {@link java.lang.String} object. */ public String getIpAddr() { return getInterface().getIpAddr(); } /** * <p>getNodeId</p> * * @return a int. */ public int getNodeId() { return getInterface().getNodeId(); } /** * <p>getNodeLabel</p> * * @return a {@link java.lang.String} object. */ public String getNodeLabel() { return getInterface().getNodeLabel(); } /** {@inheritDoc} */ protected void visitThis(PollableVisitor v) { super.visitThis(v); v.visitService(this); } /** * <p>setPollConfig</p> * * @param pollConfig a {@link org.opennms.netmgt.poller.pollables.PollableServiceConfig} object. */ public void setPollConfig(PollableServiceConfig pollConfig) { m_pollConfig = pollConfig; } /** * <p>poll</p> * * @return a {@link org.opennms.netmgt.model.PollStatus} object. */ public PollStatus poll() { PollStatus newStatus = m_pollConfig.poll(); if (!newStatus.isUnknown()) { updateStatus(newStatus); } return getStatus(); } /** * <p>getNetInterface</p> * * @throws UnknownHostException if any. * @return a {@link org.opennms.netmgt.poller.NetworkInterface} object. */ public NetworkInterface<InetAddress> getNetInterface() { return m_netInterface; } /** * <p>getAddress</p> * * @return a {@link java.net.InetAddress} object. */ public InetAddress getAddress() { return getInterface().getAddress(); } /** * <p>doPoll</p> * * @return the top changed element whose status changes needs to be processed */ public PollStatus doPoll() { if (getContext().isNodeProcessingEnabled()) { return getParent().doPoll(this); } else { resetStatusChanged(); return poll(); } } /** {@inheritDoc} */ public Event createDownEvent(Date date) { return getContext().createEvent(EventConstants.NODE_LOST_SERVICE_EVENT_UEI, getNodeId(), getAddress(), getSvcName(), date, getStatus().getReason()); } /** {@inheritDoc} */ public Event createUpEvent(Date date) { return getContext().createEvent(EventConstants.NODE_REGAINED_SERVICE_EVENT_UEI, getNodeId(), getAddress(), getSvcName(), date, getStatus().getReason()); } /** * <p>createUnresponsiveEvent</p> * * @param date a {@link java.util.Date} object. * @return a {@link org.opennms.netmgt.xml.event.Event} object. */ public Event createUnresponsiveEvent(Date date) { return getContext().createEvent(EventConstants.SERVICE_UNRESPONSIVE_EVENT_UEI, getNodeId(), getAddress(), getSvcName(), date, getStatus().getReason()); } /** * <p>createResponsiveEvent</p> * * @param date a {@link java.util.Date} object. * @return a {@link org.opennms.netmgt.xml.event.Event} object. */ public Event createResponsiveEvent(Date date) { return getContext().createEvent(EventConstants.SERVICE_RESPONSIVE_EVENT_UEI, getNodeId(), getAddress(), getSvcName(), date, getStatus().getReason()); } /** {@inheritDoc} */ public void createOutage(PollEvent cause) { super.createOutage(cause); getContext().openOutage(this, cause); } /** {@inheritDoc} */ protected void resolveOutage(PollEvent resolution) { super.resolveOutage(resolution); getContext().resolveOutage(this, resolution); } /** * <p>toString</p> * * @return a {@link java.lang.String} object. */ public String toString() { return getInterface()+":"+getSvcName(); } /** {@inheritDoc} */ public void processStatusChange(Date date) { if (getContext().isServiceUnresponsiveEnabled()) { if (isStatusChanged() && getStatus().equals(PollStatus.unresponsive())) { getContext().sendEvent(createUnresponsiveEvent(date)); if (m_oldStatus.equals(PollStatus.up())) resetStatusChanged(); } else if (isStatusChanged() && m_oldStatus.equals(PollStatus.unresponsive())) { getContext().sendEvent(createResponsiveEvent(date)); if (getStatus().equals(PollStatus.up())) resetStatusChanged(); } } super.processStatusChange(date); } /** {@inheritDoc} */ public void updateStatus(PollStatus newStatus) { if (!getContext().isServiceUnresponsiveEnabled()) { if (newStatus.equals(PollStatus.unresponsive())) newStatus = PollStatus.down(); } PollStatus currentStatus = getStatus(); if (!currentStatus.equals(newStatus)) { m_oldStatus = getStatus(); setStatusChangeTime(m_pollConfig.getCurrentTime()); } super.updateStatus(newStatus); if (!currentStatus.equals(newStatus)) { getSchedule().adjustSchedule(); } } /** * <p>setSchedule</p> * * @param schedule a {@link org.opennms.netmgt.scheduler.Schedule} object. */ public synchronized void setSchedule(Schedule schedule) { m_schedule = schedule; } /** * <p>getSchedule</p> * * @return a {@link org.opennms.netmgt.scheduler.Schedule} object. */ public synchronized Schedule getSchedule() { return m_schedule; } /** * <p>getStatusChangeTime</p> * * @return a long. */ public long getStatusChangeTime() { return m_statusChangeTime; } private void setStatusChangeTime(long statusChangeTime) { m_statusChangeTime = statusChangeTime; } /** * <p>isReady</p> * * @return a boolean. */ public boolean isReady() { /* FIXME: There is a bug in the Scheduler that only checks the first service in a queue. * If a thread hangs the below line will cause all services with the same interval to get * hang behind a service that is blocked if it has the same polling interval. The below would * be the optimal way to do it to promote fairness but... not for now. */ //return isTreeLockAvailable(); return true; } /* (non-Javadoc) * @see java.lang.Runnable#run() */ /** * <p>run</p> */ public void run() { doRun(500); } /** * <p>doRun</p> * * @return a {@link org.opennms.netmgt.model.PollStatus} object. */ public PollStatus doRun() { return doRun(0); } private PollStatus doRun(int timeout) { long startDate = System.currentTimeMillis(); log().debug("Start Scheduled Poll of service "+this); PollStatus status; if (getContext().isNodeProcessingEnabled()) { PollRunner r = new PollRunner(); try { withTreeLock(r, timeout); } catch (LockUnavailable e) { log().info("Postponing poll for "+this+" because "+e); throw new PostponeNecessary("LockUnavailable postpone poll"); } status = r.getPollStatus(); } else { doPoll(); processStatusChange(new Date()); status = getStatus(); } if (log().isDebugEnabled()) log().debug("Finish Scheduled Poll of service "+this+", started at "+new Date(startDate)); return status; } private ThreadCategory log() { return ThreadCategory.getInstance(PollableService.class); } /** * <p>delete</p> */ public void delete() { Runnable r = new Runnable() { public void run() { PollableService.super.delete(); m_schedule.unschedule(); } }; withTreeLock(r); } /** * <p>schedule</p> */ public void schedule() { if (m_schedule == null) throw new IllegalStateException("Cannot schedule a service whose schedule is set to null"); m_schedule.schedule(); } /** * <p>sendDeleteEvent</p> */ public void sendDeleteEvent() { getContext().sendEvent(getContext().createEvent(EventConstants.DELETE_SERVICE_EVENT_UEI, getNodeId(), getAddress(), getSvcName(), new Date(), getStatus().getReason())); } /** * <p>refreshConfig</p> */ public void refreshConfig() { m_pollConfig.refresh(); } /** * <p>refreshThresholds</p> */ public void refreshThresholds() { m_pollConfig.refreshThresholds(); } public String getSvcUrl() { return null; } }