/* * 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.admin.DestroyAdmin; import net.jini.admin.Administrable; import net.jini.config.Configuration; import net.jini.config.ConfigurationProvider; import net.jini.config.EmptyConfiguration; import net.jini.constraint.BasicMethodConstraints; import net.jini.core.constraint.ConnectionRelativeTime; import net.jini.core.constraint.InvocationConstraints; import net.jini.core.constraint.MethodConstraints; import net.jini.core.constraint.RemoteMethodControl; import net.jini.core.discovery.LookupLocator; import net.jini.core.entry.Entry; import net.jini.core.lookup.ServiceID; import net.jini.core.lookup.ServiceItem; import net.jini.core.lookup.ServiceTemplate; import net.jini.discovery.DiscoveryGroupManagement; import net.jini.discovery.DiscoveryLocatorManagement; import net.jini.discovery.DiscoveryManagement; import net.jini.id.ReferentUuid; import net.jini.id.Uuid; import net.jini.id.UuidFactory; import net.jini.io.MarshalledInstance; import net.jini.lease.LeaseRenewalManager; import net.jini.lookup.LookupCache; import net.jini.lookup.ServiceDiscoveryEvent; import net.jini.lookup.ServiceDiscoveryManager; import net.jini.lookup.entry.Name; import net.jini.security.BasicProxyPreparer; import net.jini.security.ProxyPreparer; import org.rioproject.admin.MonitorableService; import org.rioproject.admin.ServiceActivityProvider; import org.rioproject.admin.ServiceBeanAdmin; import org.rioproject.associations.AssociationDescriptor; import org.rioproject.associations.AssociationType; import org.rioproject.deploy.*; import org.rioproject.entry.ComputeResourceInfo; import org.rioproject.impl.client.DiscoveryManagementPool; import org.rioproject.impl.client.ServiceDiscoveryAdapter; import org.rioproject.impl.fdh.FaultDetectionHandler; import org.rioproject.impl.fdh.FaultDetectionListener; import org.rioproject.impl.fdh.PooledFaultDetectionHandler; import org.rioproject.impl.loader.ClassBundleLoader; import org.rioproject.impl.opstring.OpStringFilter; import org.rioproject.impl.service.ServiceResource; import org.rioproject.impl.servicebean.ServiceElementUtil; import org.rioproject.impl.util.ThrowableUtil; import org.rioproject.monitor.ProvisionMonitor; import org.rioproject.monitor.ProvisionMonitorEvent; import org.rioproject.monitor.service.channel.ServiceChannel; import org.rioproject.monitor.service.channel.ServiceChannelEvent; import org.rioproject.monitor.service.channel.ServiceChannelListener; import org.rioproject.monitor.service.managers.IdleServiceManager; import org.rioproject.monitor.service.util.LoggingUtil; import org.rioproject.opstring.*; import org.rioproject.opstring.ServiceElement.ProvisionType; import org.rioproject.sla.SLA; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.rmi.MarshalledObject; import java.rmi.NoSuchObjectException; import java.rmi.RemoteException; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; /** * ServiceElementManager is used to manage the discovery and dispatch * (provision) request for a Service within an OperationalString * * @author Dennis Reedy */ /* PMD will warn that setServiceElement() gets called. Its okay that we call it in the constructor */ @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") public class ServiceElementManager implements InstanceIDManager { /** The ServiceElement */ private ServiceElement svcElement; private final Object svcElementRWLock = new Object(); /** The number of services to maintain */ private int maintain=0; /** The number of services to maintain, as initially set when this manager * had it's ServiceElement set */ private int initialMaintain=0; /** A client listening for Service discovery */ private ServiceDiscoveryManager sdm; /** The LookupCache for the ServiceDiscoveryManager */ private LookupCache lCache; /** The interfaces used to discover the service */ private Class[] interfaces; /** Utility used to send provision requests */ private final ServiceProvisioner provisioner; /** Shutdown mode */ private final AtomicBoolean shutdown=new AtomicBoolean(false); /** A collection of known services */ private final List<Object> services = Collections.synchronizedList(new ArrayList<Object>()); /** A table of services that have been provisioned, but whose proxies * (or stubs) do not support the ReferentUuid interface */ private final Map<Object, String> ambiguousServices = new Hashtable<Object, String>(); /** Whether this ServiceElementManager has been started */ private final AtomicBoolean svcManagerStarted = new AtomicBoolean(false); /** The OperationalStringManager for the ServiceElementManager */ private final OperationalStringManager opStringMgr; /** Is informed that a service has been provisioned successfully */ private final ProvisionListener listener = new ServiceBeanProvisionListener(); /** Is informed if a service is detected to have failed */ private final ServiceFaultListener serviceFaultListener = new ServiceFaultListener(); /** Table of service IDs to FaultDetectionHandler instances, one for each service */ //private final Map<ServiceID, FaultDetectionHandler> fdhTable = new ConcurrentHashMap<ServiceID, FaultDetectionHandler>(); /** A List of ServiceBeanInstances */ private final List<ServiceBeanInstance> serviceBeanList = new ArrayList<ServiceBeanInstance>(); /** A List of ServiceBeanInstances which have been decremented and are not * part of the list of ServiceBeanInstances. If a service is decremented, * the ServiceBeanInstance decremented is taken from the serviceBeanList * and placed onto this list until that service has terminated, upon which * the instance will be 'cleaned' from the system */ private final List<ServiceBeanInstance> decrementedServiceBeanList = new ArrayList<ServiceBeanInstance>(); /** A List of ProvisionRequest instances correlating to redeploy requests */ private final List<ProvisionRequest> redeployRequestList = Collections.synchronizedList(new ArrayList<ProvisionRequest>()); /** Property that indicates the mode of the ServiceElementManager. If * active is true, the ServiceElementManager will actively provision * services based on attributes set in the ServiceElementManager. If active * is false, the ServiceElementManager will keep track of the service * described by the ServiceElement but not issue provision requests to the * ServiceProvisioner unless the active flag is set to true. This property * defaults to true */ private final AtomicBoolean active = new AtomicBoolean(true); /** Configuration object passed from ProvisionMonitor */ private Configuration config; /** The Uuid of the ProvisionMonitorImpl. If the uuid of a discovered * service matches our uuid, don't spend the overhead of creating a * FaultDetectionHandler */ private final Uuid myUuid; /** The idle time to check. */ private long idleTime; private final AtomicReference<IdleServiceManager> idleServiceManager = new AtomicReference<IdleServiceManager>(); /** LookupCache listener */ private ServiceElementManagerServiceListener sElemListener; /** Event source */ private ProvisionMonitor eventSource; /** Event processor */ private ProvisionMonitorEventProcessor eventProcessor; private final InstanceIDManager instanceIDMgr; /** Collection of known/allocated instance IDs. */ private final List<Long> instanceIDs = Collections.synchronizedList(new ArrayList<Long>()); /** A ProxyPreparer for discovered services */ private ProxyPreparer proxyPreparer; private final LocalServiceChannelClient localServiceChannelClient = new LocalServiceChannelClient(); /** Logger instance */ private static final Logger logger = LoggerFactory.getLogger(ServiceElementManager.class); /** Logger instance for ServiceElementManager details */ private static final Logger mgrLogger = LoggerFactory.getLogger("org.rioproject.monitor.services"); /** Logger instance for ServiceBeanInstance tracking */ private static final Logger sbiLogger = LoggerFactory.getLogger(InstanceIDManager.class); /** Used to access service provisioning configuration */ private static final String SERVICE_PROVISION_CONFIG_COMPONENT="service.provision"; private FaultDetectionHandler<ServiceID> faultDetectionHandler; /** * Construct a ServiceElementManager * * @param sElem The ServiceElement * @param opStringMgr The OperationalStringManager for the ServiceElement * @param provisioner The ServiceProvisioner * @param uuid The Uuid of the ProvisionMonitorImpl. If the uuid of a * discovered service matches our uuid, dont spend the overhead of creating * a FaultDetectionHandler * @param active Specifies the mode of the ServiceElementManager. If active * is true, the ServiceElementManager will actively provision services based * on attributes set in the ServiceElementManager. If active is false, the * ServiceElementManager will keep track of the service described by the * ServiceElement but not issue provision requests to the ServiceProvisioner * unless the active flag is set to true * @param config Configuration object * * @throws Exception if errors occur */ ServiceElementManager(final ServiceElement sElem, final OperationalStringManager opStringMgr, final ServiceProvisioner provisioner, final Uuid uuid, final boolean active, final Configuration config) throws Exception { if(sElem==null) throw new IllegalArgumentException("sElem is null"); if(opStringMgr==null) throw new IllegalArgumentException("opStringMgr is null"); if(provisioner==null) throw new IllegalArgumentException("provisioner is null"); if(uuid==null) throw new IllegalArgumentException("uuid is null"); this.opStringMgr = opStringMgr; this.provisioner = provisioner; this.myUuid = uuid; this.active.set(active); this.config = config; instanceIDMgr = this; setServiceElement(sElem); } /** * Set the ServiceElement for the ServiceElementManager * * @param newElem The ServiceEle * * @throws Exception if there are errors setting the element */ void setServiceElement(final ServiceElement newElem) throws Exception { boolean update = (this.svcElement != null); ServiceElement preElem = svcElement; this.svcElement = newElem; ServiceChannel channel = ServiceChannel.getInstance(); channel.unsubscribe(localServiceChannelClient); for (AssociationDescriptor aDesc : svcElement.getAssociationDescriptors()) { if (aDesc.getAssociationType() == AssociationType.COLOCATED) { channel.subscribe(localServiceChannelClient, aDesc, ServiceChannelEvent.Type.PROVISIONED); } } ServiceBeanConfig sc = svcElement.getServiceBeanConfig(); Map<String, Object> configParameters = sc.getConfigurationParameters(); String[] args = (String[])configParameters.get(ServiceBeanConfig.SERVICE_PROVISION_CONFIG); MethodConstraints serviceListenerConstraints= new BasicMethodConstraints(new InvocationConstraints(new ConnectionRelativeTime(30000), null)); ProxyPreparer defaultProxyPreparer = new BasicProxyPreparer(false, serviceListenerConstraints, null); if(args==null) { proxyPreparer = defaultProxyPreparer; } else { /* Service specific provisioning config */ Configuration serviceProvisionConfig = ConfigurationProvider.getInstance(args); proxyPreparer = (ProxyPreparer) serviceProvisionConfig.getEntry(SERVICE_PROVISION_CONFIG_COMPONENT, "proxyPreparer", ProxyPreparer.class, defaultProxyPreparer); } /* Get the Class[] of interfaces to discover, simple for loop, * execute it twice if this is an update and the codebase has issues */ Exception toThrow = null; for(int i=0; i<2; i++) { try { this.interfaces = loadInterfaceClasses(svcElement); toThrow = null; break; } catch(ClassNotFoundException e) { toThrow = e; /* If this is an update action, try to fix this by checking if * the codebases are different between the old and the new * ServiceElement. If so then try and repair it */ if(update) { ClassBundle[] oldBundles = preElem.getExportBundles(); ClassBundle[] newBundles = svcElement.getExportBundles(); String cb = oldBundles[0].getCodebase(); if(!cb.equals(newBundles[0].getCodebase())) { for (ClassBundle newBundle : newBundles) { newBundle.setCodebase(cb); } } } else { StringBuilder sb = new StringBuilder(); for(URL u : svcElement.getExportURLs()) { if(sb.length()>0) sb.append(", "); sb.append(u.toExternalForm()); } logger.warn("Failed ClassBundle: {}", sb.toString()); break; } } } if(toThrow!=null) throw toThrow; this.maintain = svcElement.getPlanned(); /* Set the initial planned services */ Integer ips = (Integer)svcElement.getServiceBeanConfig() .getConfigurationParameters() .get(ServiceBeanConfig.INITIAL_PLANNED_SERVICES); if(ips==null) setInitialPlanned(svcElement.getPlanned()); if(update) { /* If there is a change in provision types, adjust * pending managers */ if(svcElement.getProvisionType() != preElem.getProvisionType()) { if(preElem.getProvisionType() == ProvisionType.FIXED) { removeFixedServiceRequests(preElem); } else { provisioner.getPendingManager().removeServiceElement(preElem); } } synchronized(serviceBeanList) { for (ServiceBeanInstance sbi : serviceBeanList) { Long instanceID = sbi.getServiceBeanConfig().getInstanceID(); ServiceBeanConfig updated = newElem.getServiceBeanConfig(); Map<String, Object> configParms = updated.getConfigurationParameters(); configParms.put(ServiceBeanConfig.INSTANCE_ID, instanceID); ServiceBeanConfig newConfig = new ServiceBeanConfig(configParms, updated.getConfigArgs()); ServiceBeanConfig sbc = sbi.getServiceBeanConfig(); Map<String, Object> initParms = sbc.getInitParameters(); for (Map.Entry<String, Object> e : initParms.entrySet()) { newConfig.addInitParameter(e.getKey(), e.getValue()); } if(!sbc.getAdditionalEntries().isEmpty()) { List<Entry> entries = sbc.getAdditionalEntries(); newConfig.addAdditionalEntries(entries.toArray(new Entry[entries.size()])); } sbi.setServiceBeanConfig(newConfig); } } /* Check if the DiscoveryManagement groups or locators have * been changed */ if(sdm!=null) { /* Update groups if they have changed */ if(ServiceElementUtil.hasDifferentGroups(preElem, newElem)) { String[] groups = newElem.getServiceBeanConfig().getGroups(); if(mgrLogger.isTraceEnabled()) { StringBuilder buffer = new StringBuilder(); if(groups == DiscoveryGroupManagement.ALL_GROUPS) buffer.append("ALL_GROUPS"); else { for(int i=0; i<groups.length; i++) { if(i>0) buffer.append(", "); if(groups[i].equals("")) buffer.append("<public>"); else buffer.append(groups[i]); } } mgrLogger.trace("[{}] Discovery has changed, setting groups to : {}", LoggingUtil.getLoggingName(svcElement), buffer.toString()); } DiscoveryManagement dMgr = sdm.getDiscoveryManager(); ((DiscoveryGroupManagement)dMgr).setGroups(groups); } /* Update locators if they have changed */ if(ServiceElementUtil.hasDifferentLocators(preElem, newElem)) { LookupLocator[] locators = newElem.getServiceBeanConfig().getLocators(); if(mgrLogger.isTraceEnabled()) { StringBuilder buffer = new StringBuilder(); if(locators==null) buffer.append("null"); else { for(int i=0; i<locators.length; i++) { if(i>0) buffer.append(", "); buffer.append(locators[i].toString()); } } mgrLogger.trace("[{}] Discovery has changed, setting locators to : {}", LoggingUtil.getLoggingName(svcElement), buffer.toString()); } DiscoveryManagement dMgr = sdm.getDiscoveryManager(); ((DiscoveryLocatorManagement)dMgr).setLocators(locators); } } } /* TODO: Check if the groups the service requires are available */ if(svcManagerStarted.get()) { notifyPendingManager(null); } } void setIdleTime(long idleTime) { this.idleTime = idleTime; } /* * Get the ServiceStatement, including all ServiceRecords, for the * ServiceElement being managed */ ServiceStatement getServiceStatement() { ServiceStatement statement = new ServiceStatement(svcElement); InstantiatorResource[] resources = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); for(InstantiatorResource ir : resources) { try { ServiceRecord[] records = ir.getServiceRecords(svcElement); for(ServiceRecord record : records) statement.putServiceRecord(ir.getInstantiatorUuid(), record); } catch (RemoteException e) { mgrLogger.warn("Could not obtain ServiceRecords from {}", ir.getName(), e); } } return statement; } /* * For each ServiceBeanInstance with a non-null ServiceBeanInstantiator * Uuid, get the ServiceBeanInstantiator's ResourceCapability */ List<DeployedService> getServiceDeploymentList() { List<DeployedService> list = new ArrayList<DeployedService>(); InstantiatorResource[] resources = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); for(ServiceBeanInstance sbi : getServiceBeanInstances()) { for(InstantiatorResource ir : resources) { if(sbi.getServiceBeanInstantiatorID()!=null && sbi.getServiceBeanInstantiatorID().equals( ir.getInstantiatorUuid())) { list.add(ir.getServiceDeployment(svcElement, sbi)); break; } } } return list; } private void setInitialPlanned(final int value) { initialMaintain = value; svcElement.setServiceBeanConfig(ServiceElementUtil.addConfigParameter(svcElement.getServiceBeanConfig(), ServiceBeanConfig.INITIAL_PLANNED_SERVICES, value)); } /* * Load interfaces for the service */ private Class[] loadInterfaceClasses(final ServiceElement elem) throws MalformedURLException, ClassNotFoundException { ClassBundle[] exportBundles = elem.getExportBundles(); Class[] classes = new Class[exportBundles.length]; for(int i = 0; i < classes.length; i++) { classes[i] = ClassBundleLoader.loadClass(exportBundles[i]); /* Clear jars and codebase in the export bundles if the export bundles have been configured * with an artifact. This will allow downstream processing (in cybernodes) to ensure they * are resolved */ if(exportBundles[i].getArtifact()!=null) { exportBundles[i].setCodebase(null); exportBundles[i].setJARs(""); } } return(classes); } /** * Notify the appropriate PendingServiceElementManager * * @param provListener the ServiceProvisionListener to notify */ private void notifyPendingManager(final ServiceProvisionListener provListener) { if(!active.get()) { /* If the ServiceElement is dynamic and it is in the pending queue, * remove ProvisionRequest instances from the PendingManager */ if(svcElement.getProvisionType()==ProvisionType.DYNAMIC) { if(provisioner.getPendingManager().hasServiceElement(svcElement)) { mgrLogger.debug("Remove [{}] from PendingServiceManager", LoggingUtil.getLoggingName(svcElement)); provisioner.getPendingManager().removeServiceElement(svcElement); } } /* If the ServiceElement is fixed, then use the FixedServiceManager * to remove ProvisionRequest instances */ if(svcElement.getProvisionType()==ProvisionType.FIXED) { removeFixedServiceRequests(svcElement); } } else { /* If the ServiceElement is dynamic and it is in the pending queue, * update the ProvisionRequest instances in the PendingManager */ if(svcElement.getProvisionType()==ProvisionType.DYNAMIC) { if(provisioner.getPendingManager().hasServiceElement(svcElement)) { mgrLogger.debug("Update [{}] in PendingServiceManager", LoggingUtil.getLoggingName(svcElement)); int count = provisioner.getPendingManager().getCount(svcElement); if(count > svcElement.getPlanned()) { int toRemove = count - svcElement.getPlanned(); ProvisionRequest[] removed = provisioner.getPendingManager().removeServiceElement(svcElement, toRemove); for (ProvisionRequest aRemoved : removed) { logger.info("===> [{}] service-element: {} service-bean-config: {}", LoggingUtil.getLoggingName(svcElement), aRemoved.getServiceElement(), aRemoved.getServiceElement().getServiceBeanConfig()); removeInstanceID(aRemoved.getServiceElement().getServiceBeanConfig().getInstanceID(), "removal from pending testManager"); } } else { provisioner.getPendingManager().updateProvisionRequests(svcElement, provListener); } } verify(provListener); } /* If the ServiceElement is fixed, then use the FixedServiceManager * to update/add ProvisionRequest instances */ if(svcElement.getProvisionType()==ProvisionType.FIXED) { /* If the planned value is zero, then make sure there are no * pending requests (if there ar they will be removed), * then return */ if(svcElement.getPlanned()==0) { removeFixedServiceRequests(svcElement); return; } ProvisionRequest request = new ProvisionRequest(ServiceElementUtil.copyServiceElement(svcElement), listener, opStringMgr, instanceIDMgr); request.setServiceProvisionListener(provListener); if(provisioner.getFixedServiceManager().hasServiceElement(svcElement)) { mgrLogger.debug("Update [{}] instance in FixedServiceManager", LoggingUtil.getLoggingName(svcElement)); provisioner.getFixedServiceManager().updateProvisionRequests(svcElement, provListener); } else { /* Add the ProvisionRequest so new Cybernodes that match the * requirements will have the Service provisioned */ provisioner.getFixedServiceManager().addProvisionRequest(request, 0); mgrLogger.debug("Add [{}] to FixedServiceManager", LoggingUtil.getLoggingName(svcElement)); } /* Deploy to existing Cybernodes that match the requirements */ provisioner.getFixedServiceManager().deploy(request); } } } /** * Remove ServiceElement instances from the FixedServiceManager * * @param sElem The ServiceElement to remove */ void removeFixedServiceRequests(final ServiceElement sElem) { if(sElem.getProvisionType() != ProvisionType.FIXED) return; if(provisioner.getFixedServiceManager().hasServiceElement(sElem)){ mgrLogger.debug("Remove [{}] instances from FixedServiceManager", LoggingUtil.getLoggingName(svcElement)); provisioner.getFixedServiceManager().removeServiceElement(sElem); } } /** * Set the property that indicates the mode of the ServiceElementManager. * * @param active If active is true, the ServiceElementManager will actively * provision services based on attributes set in the ServiceElementManager. * If active is false, the ServiceElementManager will keep track of the * service described by the ServiceElement but not issue provision requests * to the ServiceProvisioner unless the active flag is set to true. */ void setActive(final boolean active) { synchronized(this) { if(!this.active.get() && active) { ServiceBeanInstance[] instances = getServiceBeanInstances(); /* If we have a collection of ServiceBeanInstance objects * but have no known instanceIDs, we need to check known * Cybernodes to fill in missing instanceIDs. * * This happens if the service described by the ServiceElement * does not implement the ServiceBeanAdmin interface, allowing * us to obtain the ServiceBeanConfig to access the * embedded instanceID */ // TODO: IS THIS CODE STILL NEEDED? if(instanceIDs.isEmpty() && instances.length>0) { InstantiatorResource[] resources = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); for(InstantiatorResource resource : resources) { try { ServiceRecord[] records = resource.getActiveServiceRecords(); for(ServiceRecord record : records) { Uuid uuid = record.getServiceID(); ServiceBeanConfig sbc = record.getServiceElement().getServiceBeanConfig(); for (ServiceBeanInstance instance : instances) { if (instance.getServiceBeanID().equals(uuid)) { instance.setServiceBeanConfig(sbc); addServiceBeanInstance(instance); Long instanceID = sbc.getInstanceID(); if (instanceID != null && !instanceIDs.contains(instanceID)) instanceIDs.add(instanceID); break; } } } } catch (Throwable e) { if (mgrLogger.isTraceEnabled()) mgrLogger.trace("Getting active ServiceRecords", e); } } } } this.active.set(active); } mgrLogger.info("Set Active [{}] for [{}]",active, LoggingUtil.getLoggingName(svcElement)); notifyPendingManager(null); } /** * Get the ServiceElement property * * @return The ServiceElement property */ public ServiceElement getServiceElement() { svcElement.setActual(getActual()); return(svcElement); } /** * Start the ServiceElementManager, initiate service discovery * * @param provListener If not <code>null</code>, the * ServiceProvisionListener to be notified of initial provisioning actions * * @return The number of services that had been discovered, had already * been running * * @throws Exception If there are any problems starting the manager */ public int startManager(final ServiceProvisionListener provListener) throws Exception { return(startManager(provListener, new ServiceBeanInstance[0])); } /** * Start the ServiceElementManager, initiate service discovery * * @param provListener If not <code>null</code>, the * ServiceProvisionListener to be notified of initial provisioning actions * @param instances Known ServiceBeanInstance objects. * @return The number of services that had been discovered, had already * been running * * @throws Exception If there are any problems starting the manager */ int startManager(final ServiceProvisionListener provListener, final ServiceBeanInstance[] instances) throws Exception { if(svcManagerStarted.get()) return(0); synchronized(this) { if(instances!=null) { for (ServiceBeanInstance instance : instances) { addServiceBeanInstance(instance); } } DiscoveryManagementPool discoPool = DiscoveryManagementPool.getInstance(); DiscoveryManagement dm = discoPool.getDiscoveryManager(svcElement.getOperationalStringName(), svcElement.getServiceBeanConfig().getGroups(), svcElement.getServiceBeanConfig().getLocators()); ServiceTemplate template; if(svcElement.getMatchOnName()) template = new ServiceTemplate(null, interfaces, new Entry[]{new Name(svcElement.getName())}); else template = new ServiceTemplate(null, interfaces, null); if(config==null) config = EmptyConfiguration.INSTANCE; sdm = new ServiceDiscoveryManager(dm, new LeaseRenewalManager(config), config); InstantiatorResource[] irArray = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); List<ServiceBeanInstance> instanceList = new ArrayList<ServiceBeanInstance>(); for (InstantiatorResource ir : irArray) { try { ServiceBeanInstance[] sbi = ir.getInstantiator().getServiceBeanInstances(svcElement); instanceList.addAll(Arrays.asList(sbi)); } catch (RemoteException e) { mgrLogger.trace("Unable to get ServiceBeanInstance(s) from {}, {}: {}", ir.getName(), e.getClass().getName(), e.getMessage()); } } lCache = sdm.createLookupCache(template, new OpStringFilter(svcElement.getOperationalStringName()), null); sElemListener = new ServiceElementManagerServiceListener(); lCache.addListener(sElemListener); if(faultDetectionHandler==null) { faultDetectionHandler = new PooledFaultDetectionHandler(); if(svcElement.getServiceBeanConfig().getFDHProperties().size()>0) faultDetectionHandler.configure(svcElement.getServiceBeanConfig().getFDHProperties()); faultDetectionHandler.setLookupCache(lCache); faultDetectionHandler.register(serviceFaultListener); } ServiceBeanInstance[] sbInstances = instanceList.toArray(new ServiceBeanInstance[instanceList.size()]); if(sbInstances.length>0) { mgrLogger.trace("ServiceElement [{}] Instantiator count={}, ServiceBeanInstance count={}, "+ "synch testManager with discovered instances", LoggingUtil.getLoggingName(svcElement), irArray.length, sbInstances.length); int lastID = 0; for (ServiceBeanInstance sbInstance : sbInstances) { Uuid uuid = sbInstance.getServiceBeanID(); Object proxy = sbInstance.getService(); if(proxy instanceof RemoteMethodControl) proxy = proxyPreparer.prepareProxy(sbInstance.getService()); ServiceID serviceID = new ServiceID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); try { setFaultDetectionHandler(proxy, serviceID); addServiceProxy(proxy); addServiceBeanInstance(sbInstance); /* Check the instanceID, make sure we maintain the * monotonically increasing requirement */ if (sbInstance.getServiceBeanConfig() != null) { Long id = sbInstance.getServiceBeanConfig().getInstanceID(); if (id != null && id.intValue() > lastID) lastID = id.intValue(); } } catch(Throwable t) { mgrLogger.warn("Unable to set FaultDetectionHandler to existing instance of [{}], " + "assume service is unavailable. {}: {}", LoggingUtil.getLoggingName(svcElement), t.getClass(), t.getMessage()); } } } else { mgrLogger.trace("ServiceElement [{}] Instantiator count={}, ServiceBeanInstance count={}, provision instances", LoggingUtil.getLoggingName(svcElement), irArray.length, sbInstances.length); } svcManagerStarted.set(true); } /* If there are any pending ServiceElement requests, reset them */ notifyPendingManager(provListener); return(services.size()); } /* * Return the started state */ public boolean isStarted() { return(svcManagerStarted.get()); } /* * If the amount of discovered service instances is less then the number to * maintain, initiate dispatch requests to the ServiceProvisioner */ void verify(final ServiceProvisionListener listener) { if(!active.get()) { return; } int pending = provisioner.getPendingManager().getCount(svcElement); mgrLogger.debug("ServiceElementManager.verify(): [{}] actual [{}], pending [{}], maintain [{}]", LoggingUtil.getLoggingName(svcElement), getActual(), pending, maintain); int actual = getActual()+pending; if(actual<maintain) dispatchProvisionRequests(listener); } /** * Destroy all discovered services this ServiceElementManager knows of */ void destroyServices() { if(sdm==null) return; ServiceBeanInstance[] instances = getServiceBeanInstances(); mgrLogger.debug("Terminating [{}] instances of [{}] ...", instances.length, LoggingUtil.getLoggingName(svcElement)); for(int i=0; i<instances.length; i++) { mgrLogger.debug("Destroying [{}] of [{}] [{}] instances ...", (i+1), instances.length, LoggingUtil.getLoggingName(svcElement)); Object proxy = null; try { proxy = instances[i].getService(); } catch(Exception e) { mgrLogger.warn("Getting service proxy", e); } if(proxy!=null) { destroyService(proxy, instances[i].getServiceBeanID(), true); } } mgrLogger.debug("Completed [{}] service termination", LoggingUtil.getLoggingName(svcElement)); } /** * Destroy a service * * @param service The ServiceItem of the service to destroy * @param serviceUuid The service Uuid * @param clean remove service references * * @return True if the service is destroyed */ boolean destroyService(final Object service, final Uuid serviceUuid, boolean clean) { boolean terminated = false; boolean forceClean = false; try { doDestroyService(service, serviceUuid, clean); terminated = true; } catch(Exception e) { if(mgrLogger.isTraceEnabled()) { mgrLogger.trace("Problem destroying Service [{}]", LoggingUtil.getLoggingName(svcElement), e); } if(!ThrowableUtil.isRetryable(e)) { mgrLogger.debug("Exception {}:{} is not retryable, force clean for [{}] ServiceBeanInstance [{}]", e.getClass().getName(), e.getMessage(), LoggingUtil.getLoggingName(svcElement), serviceUuid.toString()); forceClean = true; } else { try { doDestroyService(service, serviceUuid, clean); } catch (RemoteException e1) { mgrLogger.debug("Retried service destroy and it failed. {}:{}, force clean for [{}] ServiceBeanInstance [{}]", e1.getClass().getName(), e1.getMessage(), LoggingUtil.getLoggingName(svcElement), serviceUuid.toString()); forceClean = true; } } } ServiceBeanInstance instance; if(clean || forceClean) { instance = cleanService(service, serviceUuid, true); } else { instance = getServiceBeanInstance(serviceUuid); } /* Notify that a service has been terminated */ ProvisionMonitorEvent event = new ProvisionMonitorEvent(eventSource, ProvisionMonitorEvent.Action.SERVICE_TERMINATED, svcElement.getOperationalStringName(), svcElement, instance); processEvent(event); return(terminated); } /** * Destroy a service * * @param service The ServiceItem of the service to destroy * @param serviceUuid The service Uuid * @param clean remove service references * * @return True if the service is destroyed */ void doDestroyService(final Object service, final Uuid serviceUuid, boolean clean) throws RemoteException { logger.trace("Obtaining DestroyAdmin for [{}]", LoggingUtil.getLoggingName(svcElement)); Administrable admin = (Administrable)service; DestroyAdmin destroyAdmin = (DestroyAdmin)admin.getAdmin(); logger.trace("DestroyAdmin obtained, destroy the service [{}]", LoggingUtil.getLoggingName(svcElement)); destroyAdmin.destroy(); logger.trace("The service [{}] has been destroyed", LoggingUtil.getLoggingName(svcElement)); } /** * Relocate (move) a ServiceBean to a different ServiceBeanInstantiator * * @param instance The ServiceBeanInstance * @param svcProvisionListener the ServiceProvisionListener. May be null * @param requestedUuid The requested ServiceBeanInstatiator to relocate * to, may be null. * * @throws OperationalStringException If both the Uuid of the * ServiceBeanInstantiator cannot be obtained */ void relocate(final ServiceBeanInstance instance, final ServiceProvisionListener svcProvisionListener, final Uuid requestedUuid) throws OperationalStringException { Uuid excludeUuid = null; ServiceResource[] resources = provisioner.getServiceResourceSelector().getServiceResources(instance.getHostAddress(), true); for (ServiceResource resource : resources) { InstantiatorResource ir = (InstantiatorResource) resource.getResource(); if (ir.hasServiceElementInstance(svcElement, instance.getServiceBeanID())) { excludeUuid = ir.getInstantiatorUuid(); break; } } if(excludeUuid==null) { throw new OperationalStringException("Unable to obtain the Uuid of the instantiator"); } ServiceBeanInstance sbi = getServiceBeanInstance(instance.getServiceBeanID()); if(sbi==null) { throw new OperationalStringException("Unable to relocate service "+ "["+LoggingUtil.getLoggingName(svcElement)+"], unknown " + "ServiceBeanInstance"); } ServiceElement newElem = ServiceElementUtil.copyServiceElement(svcElement); newElem.setServiceBeanConfig(instance.getServiceBeanConfig()); ProvisionRequest request = new ProvisionRequest(newElem, listener, opStringMgr, instanceIDMgr, new RelocationListener(svcProvisionListener, instance), sbi, excludeUuid, requestedUuid, ProvisionRequest.Type.RELOCATE); doDispatchProvisionRequests(new ProvisionRequest[]{request}); } /** * Update a ServiceBeanInstance * * @param instance The ServiceBeanInstance * * @throws OperationalStringException if there are errors updating */ void update(final ServiceBeanInstance instance) throws OperationalStringException { synchronized(serviceBeanList) { int index = serviceBeanList.indexOf(instance); if(index==-1) { sbiLogger.debug("[{}] Adding ServiceBeanInstance ID {}", LoggingUtil.getLoggingName(svcElement), instance.getServiceBeanConfig().getInstanceID()); serviceBeanList.add(instance); } else { sbiLogger.debug("[{}] Updating ServiceBeanInstance ID {}", LoggingUtil.getLoggingName(svcElement), instance.getServiceBeanConfig().getInstanceID()); serviceBeanList.set(index, instance); } } } /** * Redeploy the ServiceElement * * @param svcProvisionListener A ServiceProvisionListener, to be notified * when the service either gets allocated or not */ void redeploy(final ServiceProvisionListener svcProvisionListener) { if(svcElement.getProvisionType()== ProvisionType.DYNAMIC) { provisioner.getPendingManager().updateProvisionRequests(svcElement, svcProvisionListener); } if(svcElement.getProvisionType()==ProvisionType.FIXED) { if(provisioner.getFixedServiceManager().hasServiceElement(svcElement)) { provisioner.getFixedServiceManager().updateProvisionRequests(svcElement, svcProvisionListener); } } } /** * Redeploy a service instance * * @param instance The ServiceBeanInstance * @param clean If set to true, use the original ServiceElement * configuration, not any service-specific saved state * @param sticky If true, use the Uuid of the ServiceBeanInstatiator * @param svcProvisionListener A ServiceProvisionListener, to be notified * when the service either gets allocated or not * * @throws OperationalStringException if there are errors redeploying */ void redeploy(final ServiceBeanInstance instance, final boolean clean, final boolean sticky, final ServiceProvisionListener svcProvisionListener) throws OperationalStringException { ServiceBeanInstance sbi = getServiceBeanInstance(instance.getServiceBeanID()); if(sbi==null) throw new OperationalStringException("Not tracking ServiceBeanInstance"); ServiceElement newElem = ServiceElementUtil.copyServiceElement(svcElement); if(clean) { Long instanceID = sbi.getServiceBeanConfig().getInstanceID(); newElem = ServiceElementUtil.prepareInstanceID(newElem, false, instanceID.intValue()); } else { newElem.setServiceBeanConfig(sbi.getServiceBeanConfig()); } /* If there are pending requests, the pending requests must be updated * with a new ServiceElement reflecting potentially newly created * message digests. */ if(svcElement.getProvisionType()== ProvisionType.DYNAMIC) { provisioner.getPendingManager().updateProvisionRequests(newElem, svcProvisionListener); } if(svcElement.getProvisionType()==ProvisionType.FIXED) { provisioner.getFixedServiceManager().updateProvisionRequests(newElem, svcProvisionListener); } ProvisionRequest req = new ProvisionRequest(newElem, listener, opStringMgr, instanceIDMgr, svcProvisionListener, sbi); if(sticky) req.setRequestedUuid(instance.getServiceBeanInstantiatorID()); redeployRequestList.add(req); Object proxy = null; try { proxy = instance.getService(); } catch(Exception e) { mgrLogger.warn("Getting service for destroy invocation", e); } if(proxy!=null) { boolean destroyed = destroyService(proxy, instance.getServiceBeanID(), false); /* If we couldnt destroy the instance, a false return means the * service destroy invocation resulted in an unrecoverable failure, * we can assume we will never get a serviceFailure notification. * Post the redeployment request here */ if(!destroyed) { ProvisionRequest provRequest = serviceFaultListener.getRedeploymentProvisionRequest(proxy); doDispatchProvisionRequests(new ProvisionRequest[]{provRequest}); } } } /** * Determine if a ServiceBeanInstance is tracked by this * ServiceElementManager * * @param instance The ServiceBeanInstance * * @return True if the ServiceElementManager knows about the * ServiceBeanInstance */ boolean hasServiceBeanInstance(final ServiceBeanInstance instance) { ServiceBeanInstance[] sbs = getServiceBeanInstances(); for (ServiceBeanInstance sb : sbs) { if (instance.equals(sb)) return (true); } return(false); } /** * Get the ServiceBeanInstance for a Uuid * * @param uuid The uuid * * @return A ServiceBeanInstance for the uuid, or <code>null</code> if not * found */ ServiceBeanInstance getServiceBeanInstance(final Uuid uuid) { ServiceBeanInstance instance = null; if(uuid!=null) { ServiceBeanInstance[] sbs = getServiceBeanInstances(); for (ServiceBeanInstance sb : sbs) { if (sb.getServiceBeanID().equals(uuid)) { instance = sb; break; } } } return (instance); } /* * Replace the ServiceBeanInstance */ boolean replaceServiceBeanInstance(final ServiceBeanInstance instance) { boolean replaced = false; int ndx = serviceBeanList.indexOf(instance); if(ndx!=-1) { serviceBeanList.set(ndx, instance); replaced = true; } return(replaced); } /* * Get the number of in-process provisioning requests */ int getPendingCount() { int count = -1; if(svcElement.getProvisionType()==ProvisionType.DYNAMIC) count = provisioner.getPendingManager().getCount(svcElement); return(count); } /** * Increment the number to maintain * * @param permanent Whethr the change should be set into the ServiceElement * @param svcProvisionListener the ServiceProvisionListener. May not be null * * @return An updated ServiceElement. If not incremented return null */ synchronized ServiceElement increment(final boolean permanent, final ServiceProvisionListener svcProvisionListener) { if(shutdown.get()) return null; boolean okayToIncrement = false; synchronized(svcElementRWLock) { int planned = svcElement.getPlanned(); StringBuilder sb = new StringBuilder(); sb.append("INCREMENT [") .append(LoggingUtil.getLoggingName(svcElement)) .append("] ") .append("Permanently=") .append(permanent) .append(", NUM PLANNED=") .append(planned) .append(", "); if(!permanent) { int max = getMaxServiceCount(); sb.append("MAX COUNT=").append(max).append(", "); if(planned < max) okayToIncrement = true; } else { okayToIncrement = true; } sb.append("okayToIncrement=").append(okayToIncrement); if(okayToIncrement) { svcElement.incrementPlanned(); if(permanent) { setInitialPlanned(svcElement.getPlanned()); } maintain = svcElement.getPlanned(); notifyPendingManager(svcProvisionListener); mgrLogger.debug("{}, was [{}], initialMaintain={}, new maintain={}", sb.toString(), planned, initialMaintain, maintain); } else { mgrLogger.debug("{}, cancelled, already at maximum allowed [{}]", sb.toString(), planned); } } return((okayToIncrement?svcElement:null)); } /* * Trim all pending requests */ int trim(final int trimUp) { ProvisionRequest[] removed = new ProvisionRequest[0]; if(svcElement.getProvisionType()==ProvisionType.DYNAMIC) { if(trimUp==-1) { if(provisioner.getPendingManager().hasServiceElement(svcElement)) { removed = provisioner.getPendingManager().removeServiceElement(svcElement); } } else { int numToTrim = Math.min((maintain-getActual()), trimUp); if(provisioner.getPendingManager().hasServiceElement(svcElement)) { removed = provisioner.getPendingManager().removeServiceElement(svcElement, numToTrim); } } for (ProvisionRequest aRemoved : removed) removeInstanceID(aRemoved.getServiceElement().getServiceBeanConfig().getInstanceID(), "trim"); mgrLogger.debug("Removed {} [{}] pending requests from PendingServiceManager", removed.length, LoggingUtil.getLoggingName(svcElement)); } synchronized(svcElementRWLock) { svcElement.setPlanned(svcElement.getPlanned()-removed.length); maintain = svcElement.getPlanned(); } return(removed.length); } /* * Remove and decrement the number to maintain */ synchronized ServiceElement decrement(final ServiceBeanInstance instance, final boolean mandate, final boolean destroy) { if(shutdown.get()) return null; boolean okayToDecrement = true; synchronized(svcElementRWLock) { int current = getServiceBeanInstances().length; if(current>initialMaintain) okayToDecrement = true; else if(current==initialMaintain) { if(!mandate) okayToDecrement = false; } else { if(maintain==initialMaintain && !mandate) okayToDecrement = false; } if(okayToDecrement) { svcElement.decrementPlanned(); int temp = svcElement.getPlanned(); setInitialPlanned((initialMaintain < temp?initialMaintain:temp)); } maintain = svcElement.getPlanned(); mgrLogger.debug("DECREMENT [{}] current={}, maintain={}, initialMaintain={}, mandate={}, okayToDecrement={}, destroyOnDecrement={}", LoggingUtil.getLoggingName(svcElement), current, maintain, initialMaintain, mandate, okayToDecrement, destroy); } if(okayToDecrement) { removeServiceBeanInstance(instance); removeInstanceID(instance.getServiceBeanConfig().getInstanceID(), "decrement"); synchronized(decrementedServiceBeanList) { decrementedServiceBeanList.add(instance); } notifyPendingManager(null); } if(okayToDecrement && destroy) { try { destroyService(instance.getService(), instance.getServiceBeanID(), false); } catch(Exception e) { mgrLogger.warn("Getting [{}] service for destroy invocation", LoggingUtil.getLoggingName(svcElement), e); } } return(svcElement); } /** * Remove a ServiceBeanInstance * * @param instance The ServiceBeanInstance */ void removeServiceBeanInstance(final ServiceBeanInstance instance) { synchronized(serviceBeanList) { int index = serviceBeanList.indexOf(instance); if(index!=-1) { serviceBeanList.remove(index); } } } /** * Remove a ServiceBeanInstance * * @param id The instanceID to remove * @param action The action taken */ void removeInstanceID(final Long id, final String action) { if(id!=null) { if(instanceIDs.remove(id)) { if(sbiLogger.isDebugEnabled()) { StringBuffer buff = new StringBuffer(); buff.append("[").append(svcElement.getName()).append("] ") .append("Removed [").append(LoggingUtil.getLoggingName(svcElement)) .append("] Instance ID=").append(id) .append(", ").append("Action=[").append(action).append("]\n"); instanceIDLog(buff); } } else { if(sbiLogger.isDebugEnabled()) { StringBuffer buff = new StringBuffer(); buff.append("[").append(LoggingUtil.getLoggingName(svcElement)).append("] Instance ID=") .append(id).append(" ").append("not removed for [") .append(LoggingUtil.getLoggingName(svcElement)) .append("], Action=[").append(action).append("]\n"); instanceIDLog(buff); } } } } /** * Stop the ServiceElementManager * * @param destroyServices Whether to stop the services, true to stop. This * value will be ignored if the provision type is * ServiceProvisionManagement.EXTERNAL */ public void stopManager(final boolean destroyServices) { shutdown.set(true); if(idleServiceManager.get()!=null) { idleServiceManager.get().terminate(); idleServiceManager.set(null); } /* Unsubscribe from the service channel */ ServiceChannel.getInstance().unsubscribe(localServiceChannelClient); /* Remove services from manager */ if(svcElement.getProvisionType()==ProvisionType.DYNAMIC) { provisioner.getPendingManager().removeServiceElement(svcElement); } else { provisioner.getFixedServiceManager().removeServiceElement(svcElement); } /* Remove ourselves as a LookupCache listener */ if(lCache!=null && sElemListener!=null) { try { lCache.removeListener(sElemListener); } catch (IllegalStateException e) { mgrLogger.warn("Terminating LookupCache: {}", e.getMessage()); } catch (Exception e) { mgrLogger.warn("Terminating LookupCache", e); } } /* Stop all FaultDetectionHandler instances */ if(faultDetectionHandler!=null) faultDetectionHandler.terminate(); /* If requested, destroy service instances */ if(destroyServices && svcElement.getProvisionType()!=ProvisionType.EXTERNAL) destroyServices(); /* Terminate ServiceDiscoveryManagement instances */ if(sdm!=null) { try { sdm.terminate(); } catch (Throwable t) { mgrLogger.warn("Terminating SDM", t); } } svcManagerStarted.set(false); } /* * Create and dispatch the number of ProvisionRequest instances based on * the difference between the current count of services, the number pending * and the number to maintain */ private void dispatchProvisionRequests( ServiceProvisionListener provListener) { int count = maintain-getActual(); int pending = provisioner.getPendingManager().getCount(svcElement); int numRequests = count-pending; if(numRequests<=0) return; ProvisionRequest[] requests = new ProvisionRequest[numRequests]; synchronized(svcElementRWLock) { mgrLogger.trace("Dispatch [{}] ProvisionRequests for [{}]", numRequests, LoggingUtil.getLoggingName(svcElement)); for(int i=0; i<numRequests; i++) { long instanceID = getNextInstanceID(); ServiceElement newElem = ServiceElementUtil.prepareInstanceID(svcElement, instanceID); requests[i] = new ProvisionRequest(newElem, listener, opStringMgr, instanceIDMgr, provListener, null); } } doDispatchProvisionRequests(requests); } /** * Dispatch an array of ProvisionRequest instances * * @param requests Array of ProvisionRequests */ private void doDispatchProvisionRequests(final ProvisionRequest[] requests) { /* If we are not in active mode, bail */ if(!getActive()) return; /* If we are shutting down, bail */ if(shutdown.get()) return; /* If this thing is not provisionable, get out of Dodge */ if(svcElement.getProvisionType()==ProvisionType.EXTERNAL) return; /* Or if this is not a DYNAMIC provisioning type, return */ if(svcElement.getProvisionType()!=ProvisionType.DYNAMIC) return; /* * Dispatch each ProvisionRequest */ for (ProvisionRequest request : requests) { provisioner.dispatch(request); } } /** * Get the active property * * @return The active property */ private boolean getActive() { boolean mode; synchronized(this) { mode = active.get(); } return(mode); } private int getActual() { return(getServiceBeanInstances().length); } /** * Determine if we have already discovered a service * * @param proxy The discovered service proxy * * @return Return true if the services collection contains the proxy, * otherwise return false */ private boolean alreadyDiscovered(final Object proxy) { return(services.contains(proxy)); } /* * Set the FaultDetectionHandler for a service */ private void setFaultDetectionHandler(final Object proxy, final ServiceID serviceID) throws Exception { if(serviceID==null) return; if(proxy instanceof ReferentUuid) { Uuid uuid = ((ReferentUuid)proxy).getReferentUuid(); if(myUuid.equals(uuid)) { /* Discovered instance of ourself, no FaultDetectionHandler needed */ return; } } faultDetectionHandler.monitor(proxy, serviceID); } /** * Get ServiceBeanInstance elements * * @return Array of ServiceBeanInstance objects. If there are no * ServiceBeanInstance objects, a zero-length array is returned. A new * array is returned each time */ ServiceBeanInstance[] getServiceBeanInstances() { ServiceBeanInstance[] instances; synchronized(serviceBeanList) { instances = serviceBeanList.toArray(new ServiceBeanInstance[serviceBeanList.size()]); } return(instances); } /** * Get allocated instance IDs * * @return Array of longs. If there are no allocated instance IDs, a * zero-length array is returned. A new array is returned each time */ private long[] getAllocatedIDs() { long[] ids = new long[instanceIDs.size()]; int i=0; for (Long instanceID : instanceIDs) { ids[i++] = instanceID; } return(ids); } /** * @see InstanceIDManager#getNextInstanceID */ public long getNextInstanceID() { long instanceID = ServiceElementUtil.getNextID(getAllocatedIDs()); synchronized(instanceIDs) { instanceIDs.add(instanceID); } return(instanceID); } /* * Clean up instances of a service * * @return The ServiceBeanInstance of the 'cleaned' service */ private synchronized ServiceBeanInstance cleanService(final Object proxy, final Uuid serviceUuid, final boolean removeInstanceID) { ServiceBeanInstance instance = null; ServiceBeanInstance[] instances = getServiceBeanInstances(); try { instance = findServiceBeanInstance(proxy, serviceUuid, instances, true); if(instance==null) instance = findServiceBeanInstance(proxy, serviceUuid, instances, false); if(instance!=null) { removeServiceBeanInstance(instance); if (removeInstanceID) removeInstanceID(instance.getServiceBeanConfig().getInstanceID(), "clean"); } } catch (Exception e) { mgrLogger.warn("Getting ServiceBeanInstance", e); } if(instance==null) { if(mgrLogger.isDebugEnabled()) { StringBuffer buff = new StringBuffer(); dumpInstanceIDs(buff); mgrLogger.debug("Could not find ServiceBeanInstance for [{}] UUID=[{}], " + "in known collection of ServiceBeanInstances, look in decremented list: {}", LoggingUtil.getLoggingName(svcElement), serviceUuid, decrementedServiceBeanList); } /* See if the proxy has been placed on the decrementedServiceBeanList */ List<ServiceBeanInstance> decremented = new ArrayList<ServiceBeanInstance>(); synchronized(decrementedServiceBeanList) { decremented.addAll(decrementedServiceBeanList); } try { for (ServiceBeanInstance sbi : decremented) { if (serviceUuid.equals(sbi.getServiceBeanID())) { instance = sbi; break; } } } catch (Exception e) { mgrLogger.warn("Getting ServiceBeanInstance", e); } if(instance!=null) { synchronized(decrementedServiceBeanList) { decrementedServiceBeanList.remove(instance); } } else { logger.debug("[{}] Could not locate ServiceBeanInstance {} in decremented list: {}", LoggingUtil.getLoggingName(svcElement), serviceUuid, decrementedServiceBeanList); } } InstantiatorResource[] instantiators; if(instance!=null) { mgrLogger.trace("CLEAN SBI = [{}] {}", LoggingUtil.getLoggingName(svcElement), instance.toString()); if(instance.getHostAddress()!=null) { ServiceResource[] resources = provisioner.getServiceResourceSelector().getServiceResources(instance.getHostAddress(), true); instantiators = new InstantiatorResource[resources.length]; for (int i=0; i<instantiators.length; i++) { instantiators[i] = (InstantiatorResource) resources[i].getResource(); } } else { mgrLogger.warn("ServiceBeanInstance for [{}], instance=[{}], UUID=[{}], " + "unknown host address, look across all registered Cybernodes for removal", LoggingUtil.getLoggingName(svcElement), instance.getServiceBeanConfig().getInstanceID(), serviceUuid); instantiators = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); } } else { mgrLogger.warn("No ServiceBeanInstance for service [{}], UUID=[{}], " + "look across all registered Cybernodes for removal", LoggingUtil.getLoggingName(svcElement), serviceUuid); instantiators = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); } if(mgrLogger.isDebugEnabled() && instantiators.length>0) mgrLogger.debug("Attempt to remove instance of [{}] from provided [{}] Cybernodes", LoggingUtil.getLoggingName(svcElement), instantiators.length); /* Remove all instances of the ServiceElement from InstantiatorResource objects */ for(InstantiatorResource ir : instantiators) { ServiceBeanInstance sbi = ir.removeServiceElementInstance(svcElement, instance==null?serviceUuid:instance.getServiceBeanID()); if(sbi!=null) { if(instance==null) { logger.warn("RESOLVED!!!!"); instance = sbi; } mgrLogger.debug("Removed [{}] instance from {}", LoggingUtil.getLoggingName(svcElement), ir.getName()); break; } } /* if(provisioner.getPendingManager().getCount(svcElement)>0) { mgrLogger.info("PENDING MANAGER PROCESS!!!!!!"); provisioner.getPendingManager().process(); } */ services.remove(proxy); if(idleServiceManager.get()!=null && proxy instanceof ServiceActivityProvider) { idleServiceManager.get().removeService((ServiceActivityProvider)proxy); } StringBuffer buff = new StringBuffer(); buff.append("[").append(LoggingUtil.getLoggingName(svcElement)).append("] "); buff.append("cleanService():\n"); instanceIDLog(buff); return(instance); } private ServiceBeanInstance findServiceBeanInstance(final Object proxy, final Uuid serviceUuid, final ServiceBeanInstance[] instances, final boolean matchOnProxy) throws IOException { ServiceBeanInstance instance = null; for (ServiceBeanInstance sbi : instances) { if(matchOnProxy) { try { if (sbi.getService().equals(proxy)) { instance = sbi; break; } } catch(ClassNotFoundException e) { logger.debug("{}", e.getMessage()); } } else { if (sbi.getServiceBeanID().equals(serviceUuid)) { instance = sbi; break; } } } return instance; } /* * Create a ServiceBeanInstance from a ServiceItem * * @throws IOException */ private ServiceBeanInstance createServiceBeanInstance(final ServiceItem item) throws IOException { ServiceBeanInstance instance = null; /* Create a uuid from the ServiceID */ Uuid uuid = UuidFactory.create(item.serviceID.getMostSignificantBits(), item.serviceID.getLeastSignificantBits()); /* Make sure we dont already have a ServiceBeanInstance for the item */ ServiceBeanInstance[] instances = getServiceBeanInstances(); for (ServiceBeanInstance sbi : instances) { if (sbi.getServiceBeanID().equals(uuid)) { instance = sbi; break; } } if(instance==null) { String hostName = null; String hostAddress = null; ServiceBeanConfig jsbConfig = null; Uuid instantiatorUuid = null; if(item.service instanceof Administrable) { Object admin = ((Administrable)item.service).getAdmin(); if(admin instanceof ServiceBeanAdmin) { ServiceBeanAdmin jsbAdmin = (ServiceBeanAdmin)admin; jsbConfig = jsbAdmin.getServiceElement().getServiceBeanConfig(); instantiatorUuid = jsbAdmin.getServiceBeanInstantiatorUuid(); } } ComputeResourceInfo computeResourceInfo = getComputeResourceInfo(item.attributeSets); if(computeResourceInfo!=null) { hostName = computeResourceInfo.hostName; hostAddress = computeResourceInfo.hostAddress; } if(svcElement.getProvisionType() == ProvisionType.EXTERNAL) { jsbConfig = svcElement.getServiceBeanConfig(); sbiLogger.trace("ServiceElement [{}] is an external service, create generic ServiceBeanInstance", LoggingUtil.getLoggingName(svcElement)); } /* If we couldn't get the ServiceBeanConfig or instantiatorUuid, * try to obtain it from the collection of Cybernodes */ if(jsbConfig == null || instantiatorUuid==null) { InstantiatorResource[] resources = provisioner.getServiceResourceSelector().getInstantiatorResources(svcElement); for (InstantiatorResource resource : resources) { ServiceRecord[] records = new ServiceRecord[0]; try { records = resource.getActiveServiceRecords(); } catch (Throwable t) { if (mgrLogger.isTraceEnabled()) mgrLogger.trace("Getting active ServiceRecords", t); } for (ServiceRecord record : records) { if (uuid.equals(record.getServiceID())) { if(jsbConfig==null) jsbConfig = record.getServiceElement().getServiceBeanConfig(); hostAddress = resource.getHostAddress(); instantiatorUuid = resource.getInstantiatorUuid(); break; } } } if(jsbConfig == null) { sbiLogger.trace("ServiceBeanConfiguration cannot be obtained from [{}], Proxy [{}], Uuid {}", LoggingUtil.getLoggingName(svcElement), item.service.getClass().getName(), uuid.toString()); } else { sbiLogger.trace("MATCHED\n\t[{}]\nTHIS\n\t[{}]", LoggingUtil.getLoggingName(jsbConfig), LoggingUtil.getLoggingName(svcElement)); } } if(jsbConfig!=null) { if(!instanceIDs.contains(jsbConfig.getInstanceID())) instanceIDs.add(jsbConfig.getInstanceID()); /* Create the ServiceBeanInstance */ instance = new ServiceBeanInstance(uuid, new MarshalledInstance(item.service), jsbConfig, hostName, hostAddress, instantiatorUuid); } } return(instance); } /* * Import a ServiceBeanInstance, notification from a peer */ public void importServiceBeanInstance(final ServiceBeanInstance instance) throws Exception { Object proxy = instance.getService(); if(proxy instanceof RemoteMethodControl) proxy = proxyPreparer.prepareProxy(instance.getService()); addServiceBeanInstance(instance); Uuid uuid = instance.getServiceBeanID(); ServiceID serviceID = new ServiceID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); setFaultDetectionHandler(proxy, serviceID); } /* * Add a ServiceBeanInstance */ void addServiceBeanInstance(final ServiceBeanInstance instance) { if(instance==null) return; StringBuffer buff = new StringBuffer(); buff.append("[").append(svcElement.getName()).append("] "); if(!serviceBeanList.contains(instance)) { serviceBeanList.add(instance); Long instanceID = instance.getServiceBeanConfig().getInstanceID(); if(!instanceIDs.contains(instanceID)) instanceIDs.add(instanceID); if(sbiLogger.isDebugEnabled()) buff.append("Added SBI = ") .append(instance.getServiceBeanConfig().getInstanceID()) .append(", ") .append(instance.getServiceBeanID().toString()) .append("\n"); } else { int ndx = serviceBeanList.indexOf(instance); ServiceBeanInstance current = serviceBeanList.get(ndx); /* Adjust host address */ if(current.getHostAddress()==null && instance.getHostAddress()!=null) { serviceBeanList.set(ndx, instance); if(sbiLogger.isDebugEnabled()) buff.append("Adjusted SBI host address, was [null], now = ") .append(instance.getHostAddress()) .append(", instanceID : ") .append(instance.getServiceBeanConfig()) .append("\n"); } /* Adjust instance ID */ Long iid = current.getServiceBeanConfig().getInstanceID(); if((iid==null || (iid ==0)) && instance.getServiceBeanConfig().getInstanceID()!=null) { serviceBeanList.set(ndx, instance); if(sbiLogger.isDebugEnabled()) buff.append("Adjusted SBI instanceID, was [null], now = ") .append(instance.getServiceBeanConfig().getInstanceID()) .append("\n"); } } instanceIDLog(buff); } boolean isTrackingIdleBehavior() { return idleServiceManager.get()!=null; } @SuppressWarnings("unchecked") private void addServiceProxy(final Object proxy) { services.add(proxy); } /** * Manage service provision notifications */ class ServiceBeanProvisionListener implements ProvisionListener { /** * @see ProvisionListener#uninstantiable(ProvisionRequest) */ public void uninstantiable(final ProvisionRequest request) { ServiceBeanConfig sbc; if(request.getInstance()!=null) sbc = request.getInstance().getServiceBeanConfig(); else sbc = request.getServiceElement().getServiceBeanConfig(); if(sbc!=null) { removeInstanceID(sbc.getInstanceID(), "uninstantiable"); } else { mgrLogger.warn("Received uninstantiable service notification, getServiceBeanConfig property null"); } } /** * @see ProvisionListener#serviceProvisioned(ServiceBeanInstance, InstantiatorResource) */ @SuppressWarnings({"unchecked", "PMD.AvoidReassigningParameters"}) public void serviceProvisioned(ServiceBeanInstance instance, final InstantiatorResource resource) { try { Object proxy = instance.getService(); String hostName = instance.getHostName(); if(shutdown.get()) { StringBuilder builder = new StringBuilder(); builder.append("Service Provision notification for ").append(LoggingUtil.getLoggingName(svcElement)); builder.append(" while shutting down, destroy the service instance\n"); logger.warn(builder.toString()); /* Prepare the proxy */ if(proxy instanceof RemoteMethodControl) proxy = proxyPreparer.prepareProxy(proxy); destroyService(proxy, instance.getServiceBeanID(), false); return; } synchronized(serviceBeanList) { /* Prepare the proxy */ if(proxy instanceof RemoteMethodControl) { proxy = proxyPreparer.prepareProxy(proxy); logger.trace("Prepared proxy for [{}]", LoggingUtil.getLoggingName(svcElement)); } addServiceProxy(proxy); /* If for some reason the hostName or instantiatorUuid * is null, then construct a new ServiceBeanInstance with * the hostAddress and Uuid of the InstantiatorResource */ if(hostName==null || instance.getServiceBeanInstantiatorID()==null) { instance = new ServiceBeanInstance(instance.getServiceBeanID(), instance.getMarshalledInstance(), instance.getServiceBeanConfig(), resource.getHostName(), resource.getHostAddress(), instance.getServiceBeanInstantiatorID()); } if(hasServiceBeanInstance(instance)) { replaceServiceBeanInstance(instance); } else { addServiceBeanInstance(instance); } mgrLogger.info("[{}] service provisioned, instanceId=[{}], type=[{}], have [{}] service instances", LoggingUtil.getLoggingName(svcElement), instance.getServiceBeanConfig().getInstanceID(), svcElement.getProvisionType(), serviceBeanList.size()); } /* Re-get the proxy using the proxy's classloader */ ClassLoader currentCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(proxy.getClass().getClassLoader()); proxy = new MarshalledObject(proxy).get(); if(proxy instanceof ServiceActivityProvider && idleTime>0) { synchronized (idleServiceManager) { if(idleServiceManager.get()==null) { idleServiceManager.set(new IdleServiceManager(idleTime, svcElement)); } } idleServiceManager.get().addService((ServiceActivityProvider)proxy); } if(proxy instanceof MonitorableService) { Uuid uuid = instance.getServiceBeanID(); ServiceID serviceID = new ServiceID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); setFaultDetectionHandler(proxy, serviceID); } else if(proxy instanceof ReferentUuid) { Uuid uuid = ((ReferentUuid)proxy).getReferentUuid(); ServiceID serviceID = new ServiceID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); setFaultDetectionHandler(proxy, serviceID); } else { StringBuilder sb = new StringBuilder(); for(Class c : proxy.getClass().getInterfaces()) { if(sb.length()>0) sb.append(", "); sb.append(c.getName()); } /* An ambiguous service is a service that we cannot * get the serviceID of */ mgrLogger.debug("Could not get the serviceID of [{}], [proxy={}] provisioned to [{}]. " + "Attempts will be made to resolve the serviceID of this service. " + "Proxy interfaces: \n{}", LoggingUtil.getLoggingName(svcElement), proxy.getClass().getName(), hostName, sb.toString()); ambiguousServices.put(proxy, hostName); } } catch(Exception e) { mgrLogger.warn("Unable to set or create FaultDetectionHandler for [{}]", LoggingUtil.getLoggingName(svcElement), e); } finally { Thread.currentThread().setContextClassLoader(currentCL); } } catch(Throwable t) { mgrLogger.warn("Service provision notification for [{}]", LoggingUtil.getLoggingName(svcElement), t); } /* Notify that a service has been provisioned */ ProvisionMonitorEvent event = new ProvisionMonitorEvent(eventSource, ProvisionMonitorEvent.Action.SERVICE_PROVISIONED, svcElement.getOperationalStringName(), svcElement, instance); processEvent(event); ServiceChannel channel = ServiceChannel.getInstance(); channel.broadcast(new ServiceChannelEvent(this, svcElement, ServiceChannelEvent.Type.PROVISIONED)); } } /** * Handle internal service notifications for associated service transitions */ class LocalServiceChannelClient implements ServiceChannelListener { public void notify(final ServiceChannelEvent event) { if(getActive()) { if(provisioner.getPendingManager().getCount(svcElement)>0) { provisioner.getPendingManager().process(); } } } } /** * Manage service discovery notifications */ class ServiceElementManagerServiceListener extends ServiceDiscoveryAdapter { /** * Notification that a service has been discovered * * @param sdEvent The ServiceDiscoveryEvent */ public void serviceAdded(final ServiceDiscoveryEvent sdEvent) { try { ServiceItem item = sdEvent.getPostEventServiceItem(); if(item.service==null) { mgrLogger.warn("ServiceElementManager.serviceAdded(): item.service is NULL for [{}]", LoggingUtil.getLoggingName(svcElement)); return; } if(shutdown.get()) { StringBuilder builder = new StringBuilder(); builder.append("\n*************************************************\n"); builder.append("Discovery notification for ").append(LoggingUtil.getLoggingName(svcElement)); builder.append(" while shutting down\n"); builder.append("*************************************************"); logger.warn(builder.toString()); return; } /* Prepare the proxy */ if(item.service instanceof RemoteMethodControl) item.service = proxyPreparer.prepareProxy(item.service); /* Construct the ServiceBeanInstance and add it to the serviceBeanList */ ServiceBeanInstance sbi = createServiceBeanInstance(item); if(sbi!=null) addServiceBeanInstance(sbi); /* See if this was an ambiguous service (one that we * could not obtain the serviceId for), if so clean it up */ if(ambiguousServices.containsKey(item.service)) { ambiguousServices.remove(item.service); mgrLogger.debug("Resolved ambiguous service [{}], proxy={}"+ LoggingUtil.getLoggingName(svcElement), item.service.getClass().getName()); setFaultDetectionHandler(item.service, item.serviceID); } /** * If this ServiceElementManager is active, then services will * be added as they are provisioned (through the * ServiceBeanProvisionListener). If the service is EXTERNAL, produce an event notifying * and interested listeners that the external service has been discovered. */ if(getActive()) { if(svcElement.getProvisionType()==ProvisionType.EXTERNAL) { if(alreadyDiscovered(item.service)) return; addServiceProxy(item.service); setFaultDetectionHandler(item.service, item.serviceID); /* Notify that the external service has been discovered */ ProvisionMonitorEvent event = new ProvisionMonitorEvent(eventSource, ProvisionMonitorEvent.Action.EXTERNAL_SERVICE_DISCOVERED, svcElement.getOperationalStringName(), svcElement, sbi); processEvent(event); } } else { if(alreadyDiscovered(item.service)) return; addServiceProxy(item.service); setFaultDetectionHandler(item.service, item.serviceID); } } catch(Throwable t) { mgrLogger.warn("Service discovery notification for [{}]", LoggingUtil.getLoggingName(svcElement), t); } } } /** * Manage service failure notifications */ class ServiceFaultListener implements FaultDetectionListener<ServiceID> { /** * @see org.rioproject.impl.fdh.FaultDetectionListener#serviceFailure(Object, Object) */ public synchronized void serviceFailure(final Object proxy, final ServiceID sID) { if(shutdown.get()) return; ServiceBeanInstance instance; Uuid uuid = UuidFactory.create(sID.getMostSignificantBits(), sID.getLeastSignificantBits()); mgrLogger.warn("\n********************************\n[{}] service failure, type: {}, proxy: {}, active monitor? {}\n********************************", LoggingUtil.getLoggingName(svcElement), svcElement.getProvisionType(), proxy.getClass().getName(), getActive()); try { /* Clean up instances of the service and decrease the number * of services if the service's proxy was removed from the * collection of known service proxies. If the service is a * FIXED service, clean up instanceIDs. */ instance = cleanService(proxy, uuid, (svcElement.getProvisionType() == ProvisionType.FIXED)); if(instance!=null) { mgrLogger.warn("[{}] service failure, instance: {}, host address: {}, type: {}", LoggingUtil.getLoggingName(svcElement), instance.getServiceBeanConfig().getInstanceID(), instance.getHostAddress(), svcElement.getProvisionType()); } else { mgrLogger.warn("[{}] service failure, type: {}, proxy: {}, COULD NOT OBTAIN INSTANCE, active monitor? {}", LoggingUtil.getLoggingName(svcElement), svcElement.getProvisionType(), proxy.getClass().getName(), getActive()); } String hostAddress = (instance==null?null:instance.getHostAddress()); /* If there is a ProvisionRequest in the redeployRequestList, * use that ProvisionRequest. This allows a ServiceProvisionListener to be added */ ProvisionRequest provRequest = getRedeploymentProvisionRequest(proxy); boolean asResultOfRedeployment = (provRequest!=null); /* Notify a service has failed */ if(!asResultOfRedeployment) { ProvisionMonitorEvent event = new ProvisionMonitorEvent(eventSource, ProvisionMonitorEvent.Action.SERVICE_FAILED, svcElement.getOperationalStringName(), svcElement, instance); processEvent(event); ServiceChannel channel = ServiceChannel.getInstance(); channel.broadcast(new ServiceChannelEvent(this, svcElement, ServiceChannelEvent.Type.FAILED)); } mgrLogger.trace("Redeployment ProvisionRequest for [{}] obtained: {}", LoggingUtil.getLoggingName(svcElement), (provRequest==null?"no":"yes")); if(provRequest == null) { ServiceElement newElem = ServiceElementUtil.copyServiceElement(svcElement); if(instance!=null) { newElem.setServiceBeanConfig(instance.getServiceBeanConfig()); mgrLogger.trace("[{}] found instance, instanceID={}", LoggingUtil.getLoggingName(svcElement), newElem.getServiceBeanConfig().getInstanceID()); } else { mgrLogger.trace("[{}] instance not found, use default ServiceElement settings", LoggingUtil.getLoggingName(svcElement)); } provRequest = new ProvisionRequest(newElem, listener, opStringMgr, instanceIDMgr, null, instance); } /* Add the host address to the list of hosts the service has visited */ ServiceBeanConfig sbConfig = addHost(instance, hostAddress); if(sbConfig!=null) { provRequest.getServiceElement().setServiceBeanConfig(sbConfig); } if(shutdown.get()) { logger.warn("Cancel provision task, in the process of termination for [{}]", LoggingUtil.getLoggingName(svcElement)); return; } provRequest.getServiceElement().setPlanned(maintain); if(svcElement.getProvisionType()==ProvisionType.DYNAMIC) { int pending = provisioner.getPendingManager().getCount(svcElement); //int actual = getActual()+pending; /* Do not count pending */ int actual = getActual()+pending; mgrLogger.debug("[{}] Removed: actual [{}], pending [{}], maintain [{}]", LoggingUtil.getLoggingName(svcElement), actual, pending, maintain); if(actual<maintain) { doDispatchProvisionRequests(new ProvisionRequest[]{provRequest}); } } else { logger.info("Dispatch ProvisionRequest for [{}] FIXED", LoggingUtil.getLoggingName(svcElement)); provisioner.getFixedServiceManager().deploy(provRequest, hostAddress); } } catch(Throwable t) { mgrLogger.error("Service Fault Detection for [{}]", LoggingUtil.getLoggingName(svcElement), t); } } /* * Add the host address to the host list in the ServiceBeanConfig * * @return A new ServiceBeanConfig */ @SuppressWarnings("unchecked") ServiceBeanConfig addHost(final ServiceBeanInstance instance, final String host) { ServiceBeanConfig config = null; if(instance!=null) { if(host==null) { config = instance.getServiceBeanConfig(); } else { ServiceBeanConfig current = instance.getServiceBeanConfig(); Map<String, Object> configMap = current.getConfigurationParameters(); Map<String, Object> initMap = current.getInitParameters(); List<String> seenHosts = (List)configMap.get(ServiceBeanConfig.HOST_HISTORY); List<String> hosts = new ArrayList<String>(); hosts.addAll(seenHosts); boolean addHost = true; if(!hosts.isEmpty()) { if(hosts.get(hosts.size()-1).equals(host)) addHost = false; } if(addHost) hosts.add(host); configMap.put(ServiceBeanConfig.HOST_HISTORY, hosts); config = new ServiceBeanConfig(configMap, current.getConfigArgs()); for (Map.Entry<String, Object> e : initMap.entrySet()) { config.addInitParameter(e.getKey(), e.getValue()); } } } return(config); } /* * Get a ProvisionRequest created from a redeploy invocation. If not * found return null */ ProvisionRequest getRedeploymentProvisionRequest(final Object service) { ProvisionRequest pr = null; ProvisionRequest[] prs = redeployRequestList.toArray(new ProvisionRequest[redeployRequestList.size()]); for (ProvisionRequest pr1 : prs) { try { if (pr1.getInstance() != null && pr1.getInstance().getService().equals(service)) { pr = pr1; redeployRequestList.remove(pr); break; } } catch (Exception e) { mgrLogger.warn("Getting service for redeployment invocation", e); } } return(pr); } } /** * A local ServiceProvisionListener for relocation requests */ class RelocationListener implements ServiceProvisionListener { ServiceProvisionListener remoteListener; ServiceBeanInstance original; RelocationListener(final ServiceProvisionListener remoteListener, final ServiceBeanInstance original) { this.remoteListener = remoteListener; this.original = original; } /** * Notify listener that the Service described by the ServiceBeanInstance has * been provisioned successfully * * @param jsbInstance The ServiceBeanInstance */ public void succeeded(final ServiceBeanInstance jsbInstance) throws RemoteException { try { Administrable admin = (Administrable)original.getService(); DestroyAdmin destroyAdmin = (DestroyAdmin)admin.getAdmin(); destroyAdmin.destroy(); } catch(Exception e) { if(mgrLogger.isTraceEnabled()) { mgrLogger.trace("[{}] Destroying original service", LoggingUtil.getLoggingName(svcElement), e); } else { mgrLogger.info("[{}] Destroying original service", LoggingUtil.getLoggingName(svcElement)); } } if(remoteListener != null) { try { remoteListener.succeeded(jsbInstance); } catch(Exception e) { if(mgrLogger.isTraceEnabled()) { mgrLogger.trace("[{}] Error notifying ServiceProvisionListeners on success", LoggingUtil.getLoggingName(svcElement), e); } } } } /** * Notify listener that the Service described by the ServiceElement has not * been provision successfully * * @param sElem The ServiceElement * @param resubmitted Whether the Service described by the ServiceElement * has been resubmitted for provisioning */ public void failed(final ServiceElement sElem, final boolean resubmitted) throws RemoteException { if(remoteListener != null) { try { remoteListener.failed(svcElement, true); } catch(NoSuchObjectException e) { mgrLogger.warn("ServiceBeanInstantiatorListener failure "+ "notification did not succeed, [java.rmi.NoSuchObjectException:{}], remove "+ "ServiceBeanInstantiatorListener [{}]", e.getLocalizedMessage(), remoteListener); } catch(Exception e) { mgrLogger.warn("ServiceBeanInstantiatorListener notification", e); } } } } /* * Helper method to obtain execute a * ProvisionMonitorTask to send a ProvisionMonitorEvent */ void processEvent(final ProvisionMonitorEvent event) { eventProcessor.processEvent(event); } /* * Set the event source which will be used as the source of * ProvisionFailureEvent notifications */ void setEventSource(final ProvisionMonitor eventSource) { this.eventSource = eventSource; } /* * Set the ProvisionMonitorEventProcessor */ void setEventProcessor(final ProvisionMonitorEventProcessor eventProcessor) { this.eventProcessor = eventProcessor; } /** * Helper to get the ComputeResourceInfo Entry * * @param attrs Array of Entry objects * * @return ComputeResourceInfo */ ComputeResourceInfo getComputeResourceInfo(Entry[] attrs) { for (Entry attr : attrs) { if (attr instanceof ComputeResourceInfo) { return (ComputeResourceInfo) attr; } } return(null); } /* * See if the newly discovered service can be found in an existing * Cybernode. This happens when a service is discovered that does not * implement the ServiceBeanAdmin interface. If the service had been * provisioned to a Cybernode, we should be able to get it's * ServiceBeanConfig */ void instanceIDLog(final StringBuffer buff) { if(sbiLogger.isTraceEnabled()) { dumpInstanceIDs(buff); sbiLogger.trace(buff.toString()); } } void dumpInstanceIDs(final StringBuffer buff) { long[] ids = getAllocatedIDs(); if(ids.length > 0) { buff.append("Instance ID list ["); for(int i = 0; i < ids.length; i++) { if(i > 0) buff.append(", "); buff.append(ids[i]); } buff.append("]\n"); } ServiceBeanInstance[] instances = getServiceBeanInstances(); if(instances.length == 0) { buff.append(" ServiceBeanInstance List: {empty}"); } else { buff.append(" ServiceBeanInstance List:\n"); for(int i = 0; i < instances.length; i++) { if(i > 0) buff.append("\n"); buff.append(" ").append(instances[i].toString()); } } } /* * Locate the parameter referencing the ScalingPolicyHandler and return * the number of maxServices. If either the ScalingPolicyHandler * attribute cannot be found, or the maxServices attribute in the * ScalingPolicyHandler cannot be found return -1 */ private int getMaxServiceCount() { SLA[] slas = svcElement.getServiceLevelAgreements().getServiceSLAs(); int count = -1; for (SLA sla : slas) { int x = (sla.getMaxServices()==SLA.UNDEFINED? Integer.MAX_VALUE:sla.getMaxServices()); if (x > count) count = x; } return (count); } }