001/* 002 * #%L 003 * Netarchivesuite - monitor 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.monitor.distribute; 024 025import java.util.Timer; 026import java.util.TimerTask; 027 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031import dk.netarkivet.common.CommonSettings; 032import dk.netarkivet.common.distribute.JMSConnectionFactory; 033import dk.netarkivet.common.distribute.monitorregistry.MonitorRegistryClient; 034import dk.netarkivet.common.exceptions.ArgumentNotValid; 035import dk.netarkivet.common.exceptions.NetarkivetException; 036import dk.netarkivet.common.utils.CleanupHook; 037import dk.netarkivet.common.utils.CleanupIF; 038import dk.netarkivet.common.utils.Settings; 039import dk.netarkivet.monitor.MonitorSettings; 040import dk.netarkivet.monitor.registry.distribute.RegisterHostMessage; 041 042/** 043 * The monitor registry client sends messages with JMS to register the host for JMX monitoring. 044 */ 045public final class JMSMonitorRegistryClient implements MonitorRegistryClient, CleanupIF { 046 /** The singleton instance of this class. */ 047 private static JMSMonitorRegistryClient instance; 048 /** The logger for this class. */ 049 private static final Logger log = LoggerFactory.getLogger(JMSMonitorRegistryClient.class); 050 /** The cleanup hook that will clean up this client on VM shutdown. */ 051 private CleanupHook hook; 052 /** The timer that sends messages. */ 053 private Timer registryTimer; 054 /** 055 * One minute in milliseconds. Used for control of timer task that sends messages. 056 */ 057 private static final long MINUTE_IN_MILLISECONDS = 60000L; 058 /** 059 * Zero milliseconds from now. Used for control of timer task that sends messages. 060 */ 061 private static final long NOW = 0L; 062 063 /** 064 * Intialises the client. 065 */ 066 private JMSMonitorRegistryClient() { 067 hook = new CleanupHook(this); 068 Runtime.getRuntime().addShutdownHook(hook); 069 } 070 071 /** 072 * Get the registry client singleton. 073 * 074 * @return The registry client. 075 */ 076 public static synchronized JMSMonitorRegistryClient getInstance() { 077 if (instance == null) { 078 instance = new JMSMonitorRegistryClient(); 079 } 080 return instance; 081 } 082 083 /** 084 * Register this host for monitoring. Once this method is called it will reregister for monitoring every minute, to 085 * ensure the scheduling is done. If called again, it will restart the timer that registers the host. 086 * 087 * @param localHostName The name of the host. 088 * @param jmxPort The port for JMX connections to the host. 089 * @param rmiPort The port for RMI connections for JMX communication. 090 * @throws ArgumentNotValid on null or empty localHostName, or negative port numbers. 091 */ 092 public synchronized void register(final String localHostName, final int jmxPort, final int rmiPort) { 093 ArgumentNotValid.checkNotNullOrEmpty(localHostName, "String localHostName"); 094 ArgumentNotValid.checkNotNegative(jmxPort, "int jmxPort"); 095 ArgumentNotValid.checkNotNegative(rmiPort, "int rmiPort"); 096 if (registryTimer != null) { 097 log.info("Cancelling old registryTimer instance"); 098 registryTimer.cancel(); 099 } 100 registryTimer = new Timer("Monitor-registry-client", true); 101 TimerTask timerTask = new TimerTask() { 102 /** The action to be performed by this timer task. */ 103 public void run() { 104 log.trace("Registering this client for monitoring, using hostname '{}' and JMX/RMI ports {}/{}", 105 localHostName, jmxPort, rmiPort); 106 JMSConnectionFactory.getInstance().send(new RegisterHostMessage(localHostName, jmxPort, rmiPort)); 107 } 108 }; 109 110 long reregisterDelay = Settings.getLong(MonitorSettings.DEFAULT_REREGISTER_DELAY); 111 try { 112 reregisterDelay = Long.parseLong(Settings.get(CommonSettings.MONITOR_REGISTRY_CLIENT_REREGISTERDELAY)); 113 } catch (NumberFormatException e1) { 114 log.warn("Couldn't parse setting {}. Only numbers are allowed. Using defaultvalue {}", 115 CommonSettings.MONITOR_REGISTRY_CLIENT_REREGISTERDELAY, MonitorSettings.DEFAULT_REREGISTER_DELAY); 116 } catch (NetarkivetException e2) { 117 log.warn("Couldn't find setting {}. Using defaultvalue {}", 118 CommonSettings.MONITOR_REGISTRY_CLIENT_REREGISTERDELAY, MonitorSettings.DEFAULT_REREGISTER_DELAY); 119 } 120 121 log.info("Registering this client for monitoring every {} minutes, using hostname '{}' and JMX/RMI ports {}/{}", 122 reregisterDelay, localHostName, jmxPort, rmiPort); 123 registryTimer.scheduleAtFixedRate(timerTask, NOW, reregisterDelay * MINUTE_IN_MILLISECONDS); 124 } 125 126 /** 127 * Used to clean up a class from within a shutdown hook. Must not do any logging. Program defensively, please. 128 */ 129 public synchronized void cleanup() { 130 if (registryTimer != null) { 131 registryTimer.cancel(); 132 registryTimer = null; 133 } 134 try { 135 Runtime.getRuntime().removeShutdownHook(hook); 136 } catch (IllegalStateException e) { 137 // Okay, it just means we are already shutting down. 138 } 139 hook = null; 140 } 141 142}