/* * Copyright to the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.monitor.service; import com.sun.jini.config.Config; import com.sun.jini.start.LifeCycle; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.core.entry.Entry; import net.jini.core.event.EventRegistration; import net.jini.core.event.UnknownEventException; import net.jini.core.lease.LeaseDeniedException; import net.jini.core.lease.UnknownLeaseException; import net.jini.core.lookup.ServiceID; import net.jini.export.Exporter; import net.jini.lookup.entry.ServiceInfo; import net.jini.lookup.entry.ServiceType; import net.jini.security.TrustVerifier; import net.jini.security.proxytrust.ServerProxyTrust; import org.rioproject.RioVersion; import org.rioproject.config.Constants; import org.rioproject.deploy.*; import org.rioproject.entry.StandardServiceType; import org.rioproject.event.EventDescriptor; import org.rioproject.event.EventHandler; import org.rioproject.impl.client.JiniClient; import org.rioproject.impl.event.DispatchEventHandler; import org.rioproject.impl.jmx.JMXUtil; import org.rioproject.impl.jmx.MBeanServerFactory; import org.rioproject.impl.opstring.OAR; import org.rioproject.impl.opstring.OpStringLoader; import org.rioproject.impl.service.ServiceResource; import org.rioproject.impl.servicebean.ServiceBeanActivation; import org.rioproject.impl.servicebean.ServiceBeanActivation.LifeCycleManager; import org.rioproject.impl.servicebean.ServiceBeanAdapter; import org.rioproject.impl.system.ComputeResource; import org.rioproject.impl.util.BannerProvider; import org.rioproject.impl.util.BannerProviderImpl; import org.rioproject.impl.watch.GaugeWatch; import org.rioproject.impl.watch.PeriodicWatch; import org.rioproject.impl.watch.ThreadDeadlockMonitor; import org.rioproject.loader.ServiceClassLoader; import org.rioproject.monitor.ProvisionFailureEvent; import org.rioproject.monitor.ProvisionMonitor; import org.rioproject.monitor.ProvisionMonitorEvent; import org.rioproject.monitor.proxy.ProvisionMonitorProxy; import org.rioproject.monitor.service.handlers.DeployHandler; import org.rioproject.monitor.service.handlers.DeployHandlerMonitor; import org.rioproject.monitor.service.handlers.FileSystemOARDeployHandler; import org.rioproject.monitor.service.peer.ProvisionMonitorPeer; import org.rioproject.monitor.service.persistence.StateManager; import org.rioproject.monitor.service.tasks.InitialOpStringLoadTask; import org.rioproject.monitor.service.tasks.TaskTimer; import org.rioproject.opstring.OperationalString; import org.rioproject.opstring.OperationalStringException; import org.rioproject.opstring.OperationalStringManager; import org.rioproject.resolver.Artifact; import org.rioproject.resolver.Resolver; import org.rioproject.resolver.ResolverException; import org.rioproject.resolver.ResolverHelper; import org.rioproject.servicebean.ServiceBeanContext; import org.rioproject.system.ResourceCapability; import org.rioproject.util.RioHome; import org.rioproject.util.RioManifest; import org.rioproject.util.TimeUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.management.MBeanServer; import javax.management.openmbean.*; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import java.net.MalformedURLException; import java.net.URL; import java.rmi.*; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import java.util.concurrent.TimeUnit; /** * The ProvisionMonitor service provides the capability to deploy and monitor * OperationalStrings. * * @author Dennis Reedy */ public class ProvisionMonitorImpl extends ServiceBeanAdapter implements ProvisionMonitor, ProvisionMonitorImplMBean, ServerProxyTrust { /** Component name we use to find items in the configuration */ private static final String CONFIG_COMPONENT = "org.rioproject.monitor"; /** ProvisionMonitor logger. */ private static Logger logger = LoggerFactory.getLogger(ProvisionMonitorImpl.class); /** The provisioner to use for provisioning */ private ServiceProvisioner provisioner; /** OpStringLoader for loading XML OperationalStrings */ private OpStringLoader opStringLoader; /** A watch to track how long it takes to provision services */ private GaugeWatch provisionWatch; /** Handles discovery and synchronization with other ProvisionMonitors */ private ProvisionMonitorPeer provisionMonitorPeer; private final OpStringManagerController opStringMangerController = new OpStringManagerController(); private DeploymentVerifier deploymentVerifier; private StateManager stateManager; /** A Timer used to schedule load tasks */ private TaskTimer taskTimer; private LifeCycle lifeCycle; private DeployHandlerMonitor deployMonitor; /** * Create a ProvisionMonitor * * @throws Exception If the ProvisionMonitorImpl cannot be created */ @SuppressWarnings("unused") public ProvisionMonitorImpl() throws Exception { super(); } /** * Create a ProvisionMonitor launched from the ServiceStarter framework * * @param configArgs Configuration arguments * @param lifeCycle Service lifecycle manager * * @throws Exception If the ProvisionMonitorImpl cannot be created */ @SuppressWarnings("unused") public ProvisionMonitorImpl(String[] configArgs, LifeCycle lifeCycle) throws Exception { super(); this.lifeCycle = lifeCycle; bootstrap(configArgs); } /** * Get the ServiceBeanContext and bootstrap the ProvisionMonitor * * @param configArgs configuration arguments * * @throws Exception If bootstrapping fails */ private void bootstrap(String[] configArgs) throws Exception { context = ServiceBeanActivation.getServiceBeanContext(CONFIG_COMPONENT, "ProvisionMonitor", configArgs, getClass().getClassLoader()); BannerProvider bannerProvider = (BannerProvider)context.getConfiguration().getEntry(CONFIG_COMPONENT, "bannerProvider", BannerProvider.class, new BannerProviderImpl()); logger.info(bannerProvider.getBanner(context.getServiceElement().getName())); start(context); LifeCycleManager lMgr = (LifeCycleManager)context.getServiceBeanManager().getDiscardManager(); lMgr.register(getServiceProxy(), context); } /** * Override destroy to ensure that all OpStringManagers are shutdown as well */ @Override public void destroy() { logger.debug("ProvisionMonitor: destroy() notification"); /* stop the provisioner */ if(provisioner!=null) provisioner.terminate(); /* Cleanup opStringManagers */ opStringMangerController.shutdownAllManagers(); if(deployMonitor!=null) deployMonitor.terminate(); /* Remove watches */ if(provisionWatch != null) getWatchRegistry().deregister(provisionWatch); if(taskTimer!=null) taskTimer.cancel(); /* stop the provisionMonitorPeer */ if(provisionMonitorPeer!=null) provisionMonitorPeer.terminate(); /* destroy the PersistentStore */ if(snapshotter != null) snapshotter.interrupt(); if(store != null) { try { store.destroy(); } catch(Exception t) { logger.warn("While destroying persistent store", t); } } super.destroy(); logger.info("Destroyed Monitor"); if(lifeCycle!=null) lifeCycle.unregister(this); } /** * Override parent's getAdmin to return custom service admin * * @return A ProvisionMonitorAdminProxy instance */ @Override public Object getAdmin() { if(inShutdown.get()) return null; Object adminProxy = null; try { if (admin == null) { Exporter adminExporter = getAdminExporter(); if (contextMgr != null) admin = new ProvisionMonitorAdminImpl(this, adminExporter, contextMgr.getContextAttributeLogHandler()); else admin = new ProvisionMonitorAdminImpl(this, adminExporter); } adminProxy = admin.getServiceAdmin(); } catch (Exception e) { logger.warn("Getting ProvisionMonitorAdminImpl", e); } return (adminProxy); } /** * Get the ComputeResource associated with this ProvisionMonitor * * @return The ComputeResource associated with this ProvisionMonitor */ public ComputeResource getComputeResource() { return(computeResource); } /** * Override parent's method to return <code>TrustVerifier</code> which can * be used to verify that the given proxy to this service can be trusted * * @return TrustVerifier The TrustVerifier used to verify the proxy * */ public TrustVerifier getProxyVerifier() { return (new ProvisionMonitorProxy.Verifier(getExportedProxy())); } /** * Override ServiceBeanAdapter createProxy to return a ProvisionMonitor * Proxy */ @Override protected Object createProxy() { Object proxy = ProvisionMonitorProxy.getInstance((ProvisionMonitor)getExportedProxy(), getUuid()); /* Get the registry port */ String sPort = System.getProperty(Constants.REGISTRY_PORT, "0"); int registryPort = Integer.parseInt(sPort); String name = context.getServiceBeanConfig().getName(); if(registryPort!=0) { try { Registry registry = LocateRegistry.getRegistry(registryPort); try { registry.bind(name, (Remote)proxy); logger.debug("Bound to RMI Registry on port={}", registryPort); } catch(AlreadyBoundException e) { /*ignore */ } } catch(AccessException e) { logger.warn("Binding {} to RMI Registry", name, e); } catch(RemoteException e) { logger.warn("Binding {} to RMI Registry", name, e); } } else { logger.debug("RMI Registry property not set, unable to bind {}", name); } return(proxy); } /* * Get the {@link net.jini.lookup.entry.ServiceInfo} for the Monitor */ @Override protected ServiceInfo getServiceInfo() { URL implUrl = getClass().getProtectionDomain().getCodeSource().getLocation(); RioManifest rioManifest; String build = null; try { rioManifest = new RioManifest(implUrl); build = rioManifest.getRioBuild(); } catch(IOException e) { logger.warn("Getting Rio Manifest", e); } if(build==null) build="0"; return new ServiceInfo(context.getServiceElement().getName(), "Asarian Technologies LLC", "Rio Project", RioVersion.VERSION, "Build "+build, ""); } @Override protected ServiceType getServiceType(final String name, final String comment) { StandardServiceType sType = new StandardServiceType(); sType.name = name; if(comment!=null) sType.description = comment; sType.iconName = "icon/rio-service.jpg"; return sType; } /* * @see org.rioproject.monitor.DeployAdmin#getOperationalStringManagers */ public OperationalStringManager[] getOperationalStringManagers() { if(opStringMangerController.getOpStringManagers().length==0) return (new OperationalStringManager[0]); ArrayList<OpStringManager> list = new ArrayList<OpStringManager>(); list.addAll(Arrays.asList(opStringMangerController.getOpStringManagers())); OperationalStringManager[] os = new OperationalStringManager[list.size()]; int i = 0; for (OpStringManager opMgr : list) { os[i++] = opMgr.getProxy(); } return (os); } /* * @see org.rioproject.monitor.DeployAdmin#getOperationalStringManager */ public OperationalStringManager getOperationalStringManager(String name) throws OperationalStringException { if(name==null) throw new IllegalArgumentException("name is null"); OperationalStringManager opStringManager = null; OpStringManager opMgr = opStringMangerController.getOpStringManager(name); if(opMgr!=null && opMgr.isActive()) { opStringManager = opMgr.getProxy(); } else { try { DeployAdmin dAdmin = opStringMangerController.getPrimaryDeployAdmin(name); if(dAdmin!=null) { OperationalStringManager mgr = dAdmin.getOperationalStringManager(name); if(mgr.isManaging()) { opStringManager = mgr; } } } catch(RemoteException e) { logger.debug("Communicating to peer during getOperationalStringManager for {}", name, e); } catch(OperationalStringException e) { /* ignore */ } } if(opStringManager==null) throw new OperationalStringException(String.format("Unmanaged OperationalString [%s]",name ), false); return(opStringManager); } /* * @see org.rioproject.monitor.ProvisionMonitorImplMBean#deploy */ public DeploymentResult deploy(String opStringLocation) throws MalformedURLException { if(opStringLocation == null) throw new IllegalArgumentException("argument cannot be null"); URL opStringURL = null; try { opStringURL = getArtifactURL(opStringLocation); } catch (OperationalStringException e) { e.printStackTrace(); } if(opStringURL==null) { File f = new File(opStringLocation); if(f.exists()) opStringURL = f.toURI().toURL(); else opStringURL = new URL(opStringLocation); } DeploymentResult deploymentResult; /* * The deploy call may be invoked via the MBeanServer. If it is * context classloader will not be the classloader which loaded this * bean. If the context classloader is not a ServiceClassLoader, then * set the current context classloader to be the classloader which * loaded this class. */ final Thread currentThread = Thread.currentThread(); final ClassLoader cCL = AccessController.doPrivileged( new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return (currentThread.getContextClassLoader()); } }); boolean swapCLs = !(cCL instanceof ServiceClassLoader); try { final ClassLoader myCL = AccessController.doPrivileged( new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return (getClass().getClassLoader()); } }); if(swapCLs) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { currentThread.setContextClassLoader(myCL); return (null); } }); } deploymentResult = deploy(opStringURL, null); } catch(OperationalStringException e) { Throwable cause = e.getCause(); if(cause==null) cause = e; Map<String, Throwable> m = new HashMap<String, Throwable>(); m.put(cause.getClass().getName(), cause); deploymentResult = new DeploymentResult(null, m); logger.warn("Deploying {}", opStringURL, e); } finally { if(swapCLs) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { currentThread.setContextClassLoader(cCL); return (null); } }); } } return deploymentResult; } private URL getArtifactURL(String a) throws OperationalStringException { boolean isArtifact = false; try { new Artifact(a); isArtifact = true; } catch(Exception e) { /* no-op */ } URL opStringURL = null; if(isArtifact) { try { Resolver r = ResolverHelper.getResolver(); opStringURL = r.getLocation(a, "oar"); if(opStringURL==null) throw new OperationalStringException(String.format("Artifact %s not resolvable", a)); } catch (ResolverException e) { throw new OperationalStringException(e.getLocalizedMessage(), e); } } return opStringURL; } /* * @see org.rioproject.monitor.ProvisionMonitorImplMBean#deploy */ public DeploymentResult deploy(String opStringLocation, ServiceProvisionListener listener) throws OperationalStringException { if(opStringLocation == null) throw new IllegalArgumentException("OperationalString location cannot be null"); URL opStringURL = getArtifactURL(opStringLocation); if(opStringURL==null) { try { opStringURL = new URL(opStringLocation); } catch (MalformedURLException e) { throw new OperationalStringException(String.format("Failed to create URL from %s", opStringLocation), e); } } return deploy(opStringURL, listener); } /* * @see org.rioproject.monitor.DeployAdmin#deploy */ public DeploymentResult deploy(final URL opStringUrl, ServiceProvisionListener listener) throws OperationalStringException { if(opStringUrl == null) throw new IllegalArgumentException("OperationalString URL cannot be null"); DeploymentResult deploymentResult; try { OAR oar; URL opStringUrlToUse = opStringUrl; if(opStringUrl.toExternalForm().endsWith("oar")) { oar = new OAR(opStringUrl); StringBuilder sb = new StringBuilder(); sb.append("jar:").append(oar.getURL().toExternalForm()).append("!/").append(oar.getOpStringName()); opStringUrlToUse = new URL(sb.toString()); } OperationalString[] opStrings = opStringLoader.parseOperationalString(opStringUrlToUse); if(opStrings != null && opStrings.length>0) { deploymentResult = deploy(opStrings[0], listener); } else { throw new OperationalStringException("After parsing "+opStringUrl.toExternalForm()+", " + "there were no OperationalString returned"); } } catch(Exception e) { logger.warn("Problem opening or deploying {}", opStringUrl.toExternalForm(), e); throw new OperationalStringException("Deploying OperationalString", e); } return deploymentResult; } /* * @see org.rioproject.monitor.DeployAdmin#deploy */ public DeploymentResult deploy(OperationalString opString, ServiceProvisionListener listener) throws OperationalStringException { if(opString == null) throw new IllegalArgumentException("OperationalString cannot be null"); DeploymentResult deploymentResult; try { if(!opStringMangerController.opStringExists(opString.getName())) { logger.info("Deploying Operational String [{}]", opString.getName()); DeployRequest request = new DeployRequest(opString, null); deploymentVerifier.verifyDeploymentRequest(request); Map<String, Throwable> map = new HashMap<String, Throwable>(); OpStringManager manager = opStringMangerController.addOperationalString(opString, map, null, null, listener); deploymentResult = new DeploymentResult(manager.getOperationalStringManager(), map); } else { if(logger.isInfoEnabled()) logger.info("Operational String [{}] already deployed", opString.getName()); OperationalStringManager manager = opStringMangerController.getOpStringManager(opString.getName()).getOperationalStringManager(); deploymentResult = new DeploymentResult(manager, null); } } catch(Exception e) { undeploy(opString.getName()); logger.warn("Deploying OperationalString [{}]", opString.getName(), e); if(!(e instanceof OperationalStringException)) throw new OperationalStringException(String.format("Deploying OperationalString [%s]", opString.getName()), e); throw (OperationalStringException)e; } return deploymentResult; } /* * @see org.rioproject.monitor.ProvisionMonitorImplMBean#undeploy(String) */ public boolean undeploy(String opStringName) { boolean undeployed = false; try { undeployed = undeploy(opStringName, true); } catch(OperationalStringException e) { logger.warn("Undeploying [{}]", opStringName, e); } return(undeployed); } /* * @see org.rioproject.monitor.DeployAdmin#undeploy */ public boolean undeploy(final String name, boolean terminate) throws OperationalStringException { if(name == null) throw new IllegalArgumentException("name cannot be null"); String opStringName = name; logger.info("Undeploying {}", opStringName); URL artifactURL = getArtifactURL(name); if(artifactURL!=null) { try { OAR oar = new OAR(artifactURL); OperationalString[] opstring = oar.loadOperationalStrings(); opStringName = opstring[0].getName(); } catch(Exception e) { throw new OperationalStringException(String.format("Unable to undeploy, cannot parse/load [%s]", opStringName)); } } boolean undeployed = false; OpStringManager opMgr = opStringMangerController.getOpStringManager(opStringName); logger.trace("OpStringManager: {}", opMgr); if(opMgr == null || (!opMgr.isActive())) { try { DeployAdmin dAdmin = opStringMangerController.getPrimaryDeployAdmin(opStringName); if(dAdmin!=null) { OperationalStringManager mgr = dAdmin.getOperationalStringManager(opStringName); if(mgr.isManaging()) { dAdmin.undeploy(name); undeployed = true; } } } catch(RemoteException e) { logger.debug("Communicating to peer during undeployment of [{}]", opStringName, e); } catch(OperationalStringException e) { /* ignore */ } } else { opStringMangerController.undeploy(opMgr, terminate); undeployed = true; } if(!undeployed) { throw new OperationalStringException(String.format("No deployment for [%s] found", opStringName)); } return true; } /* * @see org.rioproject.monitor.DeployAdmin#hasDeployed */ public boolean hasDeployed(String opStringName) { if(opStringName == null) throw new IllegalArgumentException("Parameters cannot be null"); for(OpStringManager opMgr : opStringMangerController.getOpStringManagers()) { if(opStringName.equals(opMgr.getName())) { return (true); } } return (false); } /* * @see org.rioproject.monitor.ProvisionMonitorImplMBean#getDeployments */ public TabularData getDeployments() { String[] itemNames = new String[] {"Name", "Status", "Role", "Deployed"}; OpenType[] itemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.DATE}; TabularDataSupport tabularDataSupport = null; try { CompositeType row = new CompositeType("Deployments", "Deployments", itemNames, itemNames, itemTypes); TabularType tabularType = new TabularType("Deployments", "Deployments", row, new String[]{"Name"}); tabularDataSupport = new TabularDataSupport(tabularType); for (OpStringManager mgr : opStringMangerController.getOpStringManagers()) { Date deployed = null; if (mgr.getDeploymentDates().length > 0) { Date[] dDates = mgr.getDeploymentDates(); deployed = dDates[dDates.length - 1]; } int status = mgr.doGetOperationalString().getStatus(); String sStatus = null; switch (status) { case OperationalString.BROKEN: sStatus = "Broken"; break; case OperationalString.COMPROMISED: sStatus = "Compromised"; break; case OperationalString.INTACT: sStatus = "Intact"; break; } String role = (mgr.isActive() ? "Primary" : "Backup"); Object[] data = new Object[]{mgr.getName(), sStatus, role, deployed}; CompositeData compositeData = new CompositeDataSupport(row, itemNames, data); tabularDataSupport.put(compositeData); } } catch(OpenDataException e) { logger.warn(e.toString(), e); } return(tabularDataSupport); } /* * @see org.rioproject.monitor.ProvisionMonitor#getPeerInfo */ public PeerInfo[] getBackupInfo() { return (provisionMonitorPeer.getBackupInfo()); } /* * @see org.rioproject.monitor.ProvisionMonitor#getPeerInfo */ public PeerInfo getPeerInfo() throws RemoteException { return (provisionMonitorPeer.doGetPeerInfo()); } /* * @see org.rioproject.monitor.ProvisionMonitor#assignBackupFor */ public boolean assignBackupFor(ProvisionMonitor primary){ return (provisionMonitorPeer.addAsBackupFor(primary)); } /* * @see org.rioproject.monitor.ProvisionMonitor#removeBackupFor */ public boolean removeBackupFor(ProvisionMonitor primary) { return (provisionMonitorPeer.removeAsBackupFor(primary)); } /* * @see org.rioproject.monitor.ProvisionMonitor#update */ public void update(PeerInfo peerInfo) { provisionMonitorPeer.peerUpdated(peerInfo); } /* * @see org.rioproject.deploy.ProvisionManager#register */ public EventRegistration register(MarshalledObject<ServiceBeanInstantiator> instantiator, MarshalledObject handback, ResourceCapability resourceCapability, List<DeployedService> deployedServices, int serviceLimit, long duration) throws LeaseDeniedException, RemoteException { return (provisioner.register(instantiator, handback, resourceCapability, deployedServices, serviceLimit, duration)); } /* * @see org.rioproject.deploy.ProvisionManager#update */ public void update(ServiceBeanInstantiator instantiator, ResourceCapability resourceCapability, List<DeployedService> deployedServices, int serviceLimit) throws UnknownLeaseException, RemoteException { /* delegate to provisioner */ provisioner.handleFeedback(instantiator, resourceCapability, deployedServices, serviceLimit); } public Collection<MarshalledObject<ServiceBeanInstantiator>> getWrappedServiceBeanInstantiators() { Collection<MarshalledObject<ServiceBeanInstantiator>> marshalledWrappers = new ArrayList<MarshalledObject<ServiceBeanInstantiator>>(); ServiceResource[] resources = provisioner.getServiceResourceSelector().getServiceResources(); logger.info("Returned {} service resources", resources.length); for(ServiceResource s : resources) { marshalledWrappers.add(((InstantiatorResource)s.getResource()).getWrappedServiceBeanInstantiator()); } return marshalledWrappers; } /* * @see org.rioproject.deploy.ProvisionManager#getServiceBeanInstantiators */ public ServiceBeanInstantiator[] getServiceBeanInstantiators() { ServiceResource[] resources = provisioner.getServiceResourceSelector().getServiceResources(); logger.info("Returned {} service resources", resources.length); List<ServiceBeanInstantiator> list = new ArrayList<ServiceBeanInstantiator>(); for(ServiceResource s : resources) { list.add(((InstantiatorResource)s.getResource()).getServiceBeanInstantiator()); } return list.toArray(new ServiceBeanInstantiator[list.size()]); } /** * Get the ProvisionMonitor event proxy source * * @return The ProvisionMonitor event proxy source */ protected ProvisionMonitor getEventProxy() { return((ProvisionMonitor)getServiceProxy()); } /** * Override parent initialize() method to provide specific initialization * for the ProvisionMonitor * * @param context The ServiceBeanContext */ public void initialize(ServiceBeanContext context) throws Exception { try { /* * Determine if a log directory has been provided. If so, create a * PersistentStore */ String logDirName = (String)context.getConfiguration().getEntry(CONFIG_COMPONENT, "logDirectory", String.class, null); if(logDirName != null) { stateManager = new StateManager(logDirName, opStringMangerController); logger.info("ProvisionMonitor: using absolute logdir path [{}]", store.getStoreLocation()); store.snapshot(); super.initialize(context, store); } else { super.initialize(context); } Configuration config = context.getConfiguration(); deploymentVerifier = new DeploymentVerifier(config, context.getDiscoveryManagement()); ProvisionMonitorEventProcessor eventProcessor = new ProvisionMonitorEventProcessor(config); provisionWatch = new GaugeWatch("Provision Clock", config); getWatchRegistry().register(provisionWatch); /* Wire up event handlers for the ProvisionMonitorEvent and the ProvisionFailureEvent */ EventDescriptor clientEventDesc = ProvisionMonitorEvent.getEventDescriptor(); getEventTable().put(clientEventDesc.eventID, eventProcessor.getMonitorEventHandler()); EventDescriptor failureEventDesc = ProvisionFailureEvent.getEventDescriptor(); /* EventHandler for ProvisionFailureEvent consumers */ EventHandler failureHandler = new DispatchEventHandler(failureEventDesc, config); getEventTable().put(failureEventDesc.eventID, failureHandler); registerEventAdapters(); provisioner = new ServiceProvisioner(config, getEventProxy(), failureHandler, provisionWatch); opStringMangerController.setConfig(config); opStringMangerController.setEventProcessor(eventProcessor); opStringMangerController.setServiceProvisioner(provisioner); opStringMangerController.setUuid(getUuid()); opStringMangerController.setStateManager(stateManager); opStringMangerController.setServiceProxy(getEventProxy()); opStringMangerController.setDeploymentVerifier(deploymentVerifier); if(System.getProperty(Constants.CODESERVER)==null) { System.setProperty(Constants.CODESERVER, context.getExportCodebase()); logger.warn("The system property [{}] has not been set, it has been resolved to: {}", Constants.CODESERVER, System.getProperty(Constants.CODESERVER)); } /* * Add attributes */ /* Check for JMXConnection */ addAttributes(JMXUtil.getJMXConnectionEntries()); addAttribute(ProvisionMonitorEvent.getEventDescriptor()); addAttribute(failureEventDesc); addAttributes((Entry[]) config.getEntry(CONFIG_COMPONENT, "initialLookupAttributes", Entry[].class, new Entry[0])); /* Utility for loading OperationalStrings */ opStringLoader = getOpStringLoader(); /* * If we have a persistent store, process recovered or updated * OperationalString elements */ if(stateManager!=null) { stateManager.processRecoveredOpStrings(); stateManager.processUpdatedOpStrings(); } /* * Start the ProvisionMonitorPeer */ provisionMonitorPeer = new ProvisionMonitorPeer(); provisionMonitorPeer.setComputeResource(computeResource); provisionMonitorPeer.setOpStringMangerController(opStringMangerController); provisionMonitorPeer.setEventProcessor(eventProcessor); provisionMonitorPeer.setDiscoveryManagement(context.getDiscoveryManagement()); provisionMonitorPeer.setServiceProxy(getEventProxy()); provisionMonitorPeer.setConfig(config); provisionMonitorPeer.initialize(); opStringMangerController.setProvisionMonitorPeer(provisionMonitorPeer); /* Create the task Timer */ taskTimer = TaskTimer.getInstance(); /* * Setup the DeployHandlerMonitor with DeployHandlers */ long deployMonitorPeriod = TimeUnit.SECONDS.toMillis(30); try { deployMonitorPeriod = Config.getLongEntry(config, CONFIG_COMPONENT, "deployMonitorPeriod", deployMonitorPeriod, -1, Long.MAX_VALUE); } catch(ConfigurationException e) { logger.warn("Non-fatal exception getting deployMonitorPeriod, using default value of [{}] " + "milliseconds. Continuing on with initialization.", deployMonitorPeriod, e); } if(logger.isDebugEnabled()) logger.debug("Configured to scan for OAR deployments every {}", TimeUtil.format(deployMonitorPeriod)); if(deployMonitorPeriod>0) { String rioHome = RioHome.get(); if(!rioHome.endsWith("/")) rioHome = rioHome+"/"; File deployDir = new File(rioHome+"deploy"); DeployHandler fsDH = new FileSystemOARDeployHandler(deployDir, deploymentVerifier); DeployHandler[] deployHandlers = (DeployHandler[]) config.getEntry(CONFIG_COMPONENT, "deployHandlers", DeployHandler[].class, new DeployHandler[]{fsDH}); deployMonitor = new DeployHandlerMonitor(deployHandlers, deployMonitorPeriod, opStringMangerController, getLocalDeployAdmin()); } else { logger.info("OAR hot deploy capabilities have been disabled"); } /* Get the timeout value for loading OperationalStrings */ long initialOpStringLoadDelay = TimeUnit.SECONDS.toMillis(5); try { initialOpStringLoadDelay = Config.getLongEntry(config, CONFIG_COMPONENT, "initialOpStringLoadDelay", initialOpStringLoadDelay, 1, Long.MAX_VALUE); } catch(ConfigurationException e) { logger.warn("Exception getting initialOpStringLoadDelay", e); } String[] initialOpStrings = new String[]{}; try { initialOpStrings = (String[]) config.getEntry(CONFIG_COMPONENT, "initialOpStrings", String[].class, initialOpStrings); } catch(ConfigurationException e) { logger.warn("Exception getting initialOpStrings", e); } if(logger.isDebugEnabled()) { StringBuilder builder = new StringBuilder(); for(String s : initialOpStrings) { if(builder.length()>0) builder.append(", "); builder.append(s); } logger.debug("initialOpStrings=[{}], initialOpStringLoadDelay={}", builder.toString(), initialOpStringLoadDelay); } /* * Schedule the task to Load any configured OperationalStrings */ long now = System.currentTimeMillis(); DeployAdmin dAdmin = getLocalDeployAdmin(); if(initialOpStrings.length>0) taskTimer.schedule(new InitialOpStringLoadTask(initialOpStrings, dAdmin, provisionMonitorPeer, opStringMangerController, stateManager), new Date(now+initialOpStringLoadDelay)); /* * If we were booted without a serviceID (perhaps using RMI * Activation), then create one */ if(serviceID == null) { serviceID = new ServiceID(getUuid().getMostSignificantBits(), getUuid().getLeastSignificantBits()); logger.debug("Created new ServiceID: {}", serviceID.toString()); } /* * Force a snapshot so the persistent store reflects the current * state of the Provisioner */ if(store != null) store.snapshot(); MBeanServer mbs = MBeanServerFactory.getMBeanServer(); final ThreadDeadlockMonitor threadDeadlockMonitor = new ThreadDeadlockMonitor(); ThreadMXBean threadMXBean = JMXUtil.getPlatformMXBeanProxy(mbs, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class); threadDeadlockMonitor.setThreadMXBean(threadMXBean); PeriodicWatch p = new PeriodicWatch("Thread Deadlock", config) { public void checkValue() { threadDeadlockMonitor.getThreadDeadlockCalculable(); } }; p.setPeriod(10*1000); // 10 seconds context.getWatchRegistry().register(p); p.start(); logger.info("Started Provision Monitor [{}]", JiniClient.getDiscoveryAttributes(context)); } catch(Exception e) { logger.error("Unrecoverable initialization exception", e); destroy(); } } private DeployAdmin getLocalDeployAdmin() { DeployAdmin deployAdmin = null; try { deployAdmin = (DeployAdmin) ((ProvisionMonitor)getServiceProxy()).getAdmin(); } catch (RemoteException e) { logger.warn("While trying to get the DeployAdmin", e); } return deployAdmin; } private void registerEventAdapters() throws LeaseDeniedException, UnknownEventException, RemoteException { // translate ProvisionFailureEvents to notifications EventDescriptor provisionFailureEventDescriptor = new EventDescriptor(ProvisionFailureEvent.class, ProvisionFailureEvent.ID); ProvisionFailureEventAdapter provisionFailureEventAdapter = new ProvisionFailureEventAdapter(objectName, getNotificationBroadcasterSupport()); register(provisionFailureEventDescriptor, provisionFailureEventAdapter, null, Long.MAX_VALUE); // register notification info mbeanNoticationInfoList.add(provisionFailureEventAdapter.getNotificationInfo()); // translate ProvisionMonitorEvents to notifications EventDescriptor provisionMonitorEventDescriptor = new EventDescriptor(ProvisionMonitorEvent.class, ProvisionMonitorEvent.ID ); ProvisionMonitorEventAdapter provisionMonitorEventAdapter = new ProvisionMonitorEventAdapter(objectName, getNotificationBroadcasterSupport()); register(provisionMonitorEventDescriptor, provisionMonitorEventAdapter, null, Long.MAX_VALUE); //register notification info mbeanNoticationInfoList.add(provisionMonitorEventAdapter.getNotificationInfo()); } /** * Get the OpStringloader, the utility to load OperationalStrings * * @return The OpStringLoader * * @throws Exception if the OpStringLoader cannot be created */ protected OpStringLoader getOpStringLoader() throws Exception { return(new OpStringLoader(this.getClass().getClassLoader())); } }