/* * 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.cybernode.service; import com.sun.jini.admin.DestroyAdmin; import com.sun.jini.start.LifeCycle; import groovy.lang.MissingMethodException; import net.jini.admin.Administrable; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.id.Uuid; import org.rioproject.admin.ServiceBeanControlException; import org.rioproject.associations.Association; import org.rioproject.impl.associations.DefaultAssociationManagement; import org.rioproject.associations.AssociationType; import org.rioproject.impl.bean.BeanHelper; import org.rioproject.annotation.Initialized; import org.rioproject.annotation.Started; import org.rioproject.config.Constants; import org.rioproject.impl.container.*; import org.rioproject.impl.servicebean.DefaultServiceBeanContext; import org.rioproject.impl.servicebean.DefaultServiceBeanManager; import org.rioproject.servicebean.ServiceBeanContext; import org.rioproject.costmodel.ResourceCost; import org.rioproject.deploy.ServiceBeanInstance; import org.rioproject.deploy.ServiceBeanInstantiationException; import org.rioproject.deploy.ServiceRecord; import org.rioproject.event.EventHandler; import org.rioproject.impl.exec.ServiceBeanExecHandler; import org.rioproject.impl.exec.ServiceExecutor; import org.rioproject.impl.jmx.JMXUtil; import org.rioproject.impl.jmx.MBeanServerFactory; import org.rioproject.impl.servicebean.ServiceBeanSLAManager; import org.rioproject.impl.servicebean.ServiceElementUtil; import org.rioproject.impl.opstring.OpStringManagerProxy; import org.rioproject.opstring.OperationalStringManager; import org.rioproject.opstring.ServiceElement; import org.rioproject.sla.SLAThresholdEvent; import org.rioproject.impl.system.ComputeResource; import org.rioproject.system.ComputeResourceUtilization; import org.rioproject.system.capability.PlatformCapability; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.PostConstruct; import javax.management.ObjectName; import java.lang.annotation.Annotation; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** * The ServiceBeanDelegateImpl provides loading and management services for a service * which has been instantiated by a {@link org.rioproject.impl.container.ServiceBeanContainer} * * @author Dennis Reedy */ public class ServiceBeanDelegateImpl implements ServiceBeanDelegate { /** ServiceBeanInstance of a loaded and started ServiceBean */ private ServiceBeanInstance instance; /** Unique identifier for the delegate */ private final Object identifier; /** ServiceBean ID */ private Uuid serviceID; /** ServiceBean proxy */ private Object serviceProxy; /** Reference to the ServiceBeanContainer */ private final ServiceBeanContainer container; /** The ServiceElement */ private ServiceElement sElem; /** The OperationalStringManager for the JSB */ private OperationalStringManager opStringMgr; /** Throwable for ThreadGroup processing */ private Throwable abortThrowable; /** The ServiceRecord */ private ServiceRecord serviceRecord; private final Object serviceRecordLock = new Object(); private long lastServiceRecordUpdate; /** Flag to indicate the service is in the process of starting */ private final AtomicBoolean starting = new AtomicBoolean(false); /** Flag to indicate the service is in the process of terminating */ private final AtomicBoolean terminating =new AtomicBoolean(false); /** Flag to indicate the service is terminated */ private final AtomicBoolean terminated = new AtomicBoolean(false); /** A utility used to install staged data */ private final StagedDataManager stagedDataManager; /** The ServiceBeanContext */ private ServiceBeanContext context; /** EventHandler for SLAThresholdEvent processing */ private EventHandler slaEventHandler; /* Manage declared SLAs */ private ServiceBeanSLAManager serviceBeanSLAManager; /** A ServiceElementChangeManager for handling updates to the * ServiceElement */ private ServiceElementChangeManager sElemChangeMgr; private ServiceCostCalculator serviceCostCalculator; //private ServiceProvisionEvent provisionEvent; private ServiceBeanExecHandler execManager; private final Collection<PlatformCapability> installedPlatformCapabilities = new ArrayList<PlatformCapability>(); private static final String CONFIG_COMPONENT = "org.rioproject.cybernode"; /** Logger */ private final static Logger logger = LoggerFactory.getLogger(ServiceBeanDelegateImpl.class.getName()); /** Result from loading the service */ protected ServiceBeanLoaderResult loadResult; private AtomicBoolean isDiscarded = new AtomicBoolean(false); /** * Create a ServiceBeanDelegateImpl * * @param identifier A cookie for internal accounting * @param serviceID Unique identifier for the ServiceBean * @param container The ServiceBeanContainer */ public ServiceBeanDelegateImpl(Integer identifier, Uuid serviceID, ServiceBeanContainer container) { this.identifier = identifier; this.serviceID = serviceID; this.container = container; stagedDataManager = new StagedDataManager(container.getComputeResource()); ServiceCostCalculator defaultCostCalculator = new ServiceCostCalculator(); Configuration config = container.getSharedConfiguration(); try { serviceCostCalculator = (ServiceCostCalculator)config.getEntry(CONFIG_COMPONENT, "serviceCostCalculator", ServiceCostCalculator.class, defaultCostCalculator); } catch(ConfigurationException e) { logger.warn("Getting ServiceCostCalculator, using default", e); serviceCostCalculator = defaultCostCalculator; } serviceCostCalculator.setComputeResource(container.getComputeResource()); } public void setOperationalStringManager(OperationalStringManager opStringMgr) { this.opStringMgr= opStringMgr; } public void setServiceElement(ServiceElement sElem) { this.sElem = sElem; stagedDataManager.setServiceElement(sElem); } public void setEventHandler(EventHandler slaEventHandler) { this.slaEventHandler = slaEventHandler; } /** * Get the ServiceRecord * * @return ServiceRecord */ public ServiceRecord getServiceRecord() { if(serviceRecord!=null) { synchronized(serviceRecordLock) { try { long now = System.currentTimeMillis(); if(lastServiceRecordUpdate!=0) serviceRecord.setUpdated(); long diff = (lastServiceRecordUpdate==0 ? 0 : now-lastServiceRecordUpdate); ResourceCost[] resourceCosts = serviceCostCalculator.calculateCosts(diff); for (ResourceCost resourceCost : resourceCosts) { serviceRecord.addResourceCost(resourceCost); } lastServiceRecordUpdate = now; } catch (Throwable t) { logger.warn("Calculating resource costs for [{}]", sElem.getName(), t); } } } return(serviceRecord); } public boolean isActive() { return !isDiscarded.get(); } /** * Get the ServiceElement * * @return The ServiceElement used by this ServiceBeanDelegateImpl */ public ServiceElement getServiceElement() { return(sElem); } /* * Update the ServiceElement and potentially the OperationalStringManager * if the ServiceElement is the same as the ServiceElement the delegate * has created a ServiceBean instance of */ public boolean update(ServiceElement newElem, OperationalStringManager opMgr) { if(terminated.get() || terminating.get()) return(false); if(execManager!=null) { try { long waited = 0; long totalWait = 10*1000; while(execManager.getServiceBeanExecutor()==null && waited<totalWait) { try { Thread.sleep(500); waited += 500; } catch (InterruptedException e) { return false; } } if(execManager.getServiceBeanExecutor()==null) return false; execManager.getServiceBeanExecutor().update(newElem, opMgr); return true; } catch (RemoteException e) { logger.warn("Updating forked service [{}]", ServiceLogUtil.logName(sElem), e); return false; } } if(!this.sElem.equals(newElem)) return(false); synchronized(this) { if(serviceProxy==null) { logger.trace("Cannot update [{}], Proxy is null", sElem.getName()); return(false); } /* Preserve instanceID */ Long instanceID = sElem.getServiceBeanConfig().getInstanceID(); if(instanceID!=null) { sElem = ServiceElementUtil.prepareInstanceID(newElem, true, instanceID); } else { sElem = ServiceElementUtil.copyServiceElement(newElem); logger.warn("No instanceID for [{}] to update", sElem.getName()); } if(context instanceof DefaultServiceBeanContext) { ((DefaultServiceBeanContext)context).setServiceElement(sElem); } else { logger.warn("Cannot update [{}], Unknown ServiceBeanContext type [{}]", ServiceLogUtil.logName(sElem), context.getClass().getName()); return(false); } if(context.getServiceBeanManager() instanceof DefaultServiceBeanManager) { DefaultServiceBeanManager jsbMgr = (DefaultServiceBeanManager)context.getServiceBeanManager(); OperationalStringManager mgr = jsbMgr.getOperationalStringManager(); if(mgr!=null && !(mgr instanceof OpStringManagerProxy.OpStringManager)) { jsbMgr.setOperationalStringManager(opMgr); } } else { logger.warn("Cannot update [{}], Unknown ServiceBeanManager type [{}]", sElem.getName(), context.getServiceBeanManager().getClass().getName()); return(false); } } return(true); } /** * Loads and starts a service, blocking until the service has been started * * @return The ServiceBeanInstance * * @throws org.rioproject.deploy.ServiceBeanInstantiationException if there are errors loading the service * bean */ public ServiceBeanInstance load() throws ServiceBeanInstantiationException { if(instance!=null) return(instance); synchronized(this) { startServiceBean(sElem, opStringMgr); } return(instance); } /** * Get the ServiceBeanInstance * * @return The ServiceBeanInstance */ public ServiceBeanInstance getServiceBeanInstance() { return (instance); } /** * Advertise the ServiceBean, making it available to all clients * * @throws ServiceBeanControlException if the service bean cannot be advertised */ public void advertise() throws ServiceBeanControlException { if(execManager!=null) return; if(serviceProxy==null) { throw new ServiceBeanControlException("Cannot advertise ["+sElem.getName()+"], Proxy is null"); } if(terminated.get() || terminating.get()) throw new ServiceBeanControlException("advertising service while in the process of terminating"); /* If any of the associations are of type requires, and they are lazily (not eagerly) injected, service * advertisement is managed by AssociationManagement */ for (Association association : context.getAssociationManagement().getAssociations()) { if (association.getAssociationType()== AssociationType.REQUIRES) { logger.debug("{} has at least one requires Association, advertisement managed by AssociationManagement", sElem.getName()); if(context.getAssociationManagement() instanceof DefaultAssociationManagement) { ((DefaultAssociationManagement)context.getAssociationManagement()).checkAdvertise(); } return; } } try { ServiceAdvertiser.advertise(serviceProxy, context, runningForked()); logger.debug("{}: advertised", ServiceLogUtil.logName(sElem)); } catch(ServiceBeanControlException e) { logger.warn("Could not advertise {}", sElem.getName()); throw e; } } public ComputeResourceUtilization getComputeResourceUtilization() { ComputeResourceUtilization cru = null; if(sElem.forkService()) { try { cru = execManager.getServiceBeanExecutor().getComputeResourceUtilization(); } catch (RemoteException e) { logger.warn("Getting compute resource utilization failed for " + "service [{}], the service may be " + "in the process of failing or may have already " + "failed. {}:{}", ServiceElementUtil.getLoggingName(sElem), e.getClass().getName(), e.getMessage()); } } else if(loadResult.getImpl() instanceof ServiceExecutor) { cru = ((ServiceExecutor)loadResult.getImpl()).getComputeResourceUtilization(); } else { cru = container.getComputeResource().getComputeResourceUtilization(); } return cru; } /** * Terminate the ServiceBeanDelegate. This calls the destroy method of the * ServiceBean */ public void terminate() { if(terminated.get() || terminating.get()) return; try { terminating.set(true); if(serviceBeanSLAManager != null) { serviceBeanSLAManager.terminate(); serviceBeanSLAManager = null; } if(context!=null) { /* Remove ServiceElementChangeManager */ context.getServiceBeanManager().removeListener(sElemChangeMgr); } ServiceTerminationHelper.cleanup(context); if(opStringMgr instanceof OpStringManagerProxy.OpStringManager) { ((OpStringManagerProxy.OpStringManager)opStringMgr).terminate(); } /* If we have an instance, go through service termination */ if(instance!=null) { if(serviceProxy!=null) { try { if(serviceProxy instanceof Administrable) { Administrable admin = (Administrable)serviceProxy; Object adminObject = admin.getAdmin(); if(adminObject instanceof DestroyAdmin) { DestroyAdmin destroyAdmin = (DestroyAdmin)adminObject; destroyAdmin.destroy(); setDiscarded(); //container.discarded(identifier); terminated.set(true); } else { logger.debug("No DestroyAdmin capabilities for {}", serviceProxy.getClass().getName()); } } else { logger.debug("No Administrable capabilities for {}", serviceProxy.getClass().getName()); } } catch(Throwable t) { logger.error("Terminating ServiceBean", t); terminating.set(false); } finally { serviceProxy = null; } } } /* Decrement platform capability counter */ for(PlatformCapability pCap : installedPlatformCapabilities) { int count = pCap.decrementUsage(); if(count==-1) { logger.info("PlatformCapability ["+pCap.getName()+"], unknown count"); } else { logger.info("PlatformCapability ["+pCap.getName()+"], count="+count); } } /* Unprovision any installed platform capability components */ PlatformCapability[] pCaps = stagedDataManager.removeInstalledPlatformCapabilities(false); for(PlatformCapability pCap : pCaps) { unregisterPlatformCapability(pCap); } /* Unprovision staged data*/ stagedDataManager.removeStagedData(); } finally { container.remove(identifier); if(loadResult!=null) { ServiceBeanLoader.unload(loadResult, sElem); loadResult = null; } if(context!=null && context.getServiceBeanManager() instanceof DefaultServiceBeanManager) ((DefaultServiceBeanManager)context.getServiceBeanManager()).setMarshalledInstance(null); context = null; } } /** * Load, instantiate and start the ServiceBean * * @param sElem The ServiceElement * @param opStringMgr The OperationalStringManager * * @throws org.rioproject.deploy.ServiceBeanInstantiationException if there are errors creating the * service bean */ protected void startServiceBean(final ServiceElement sElem, final OperationalStringManager opStringMgr) throws ServiceBeanInstantiationException { /* threadGroup = new ThreadGroup("ServiceBeanThreadGroup:"+sElem.getName()) { public void uncaughtException(Thread t, Throwable o) { logger.log(Level.SEVERE, "UncaughtException thrown in ServiceBean "+ "["+sElem.getName()+"]", o); } }; Thread jsbThread = new Thread(threadGroup, "ServiceBeanDelegateImpl") { */ StringBuilder threadName = new StringBuilder(); threadName.append(sElem.getName()).append("-"); Long instanceID = sElem.getServiceBeanConfig().getInstanceID(); threadName.append(instanceID==null?"<?>":instanceID).append("-delegate"); Thread jsbThread = new Thread(threadName.toString()) { public void run() { starting.set(true); ComputeResource computeResource = container.getComputeResource(); try { if(!runningForked()) { /* If there are provisionable capabilities, or * data staging, perform the stagedData/installation */ stagedDataManager.download(); installedPlatformCapabilities.addAll(stagedDataManager.getInstalledPlatformCapabilities()); for(PlatformCapability pCap : installedPlatformCapabilities) { int count = pCap.incrementUsage(); logger.info("PlatformCapability ["+getName()+"], count="+count); } } /* Check if we are forking a service bean */ if(sElem.forkService() && !runningForked()) { logger.debug("Fork required for {}", ServiceLogUtil.logName(sElem)); logger.trace("Created a ServiceBeanExecHandler for {}", ServiceLogUtil.logName(sElem)); execManager = new ServiceBeanExecHandler(sElem, container.getSharedConfiguration(), container.getUuid()); try { /* Get matched PlatformCapability instances to apply */ PlatformCapability[] pCaps = computeResource.getPlatformCapabilities(); PlatformCapability[] matched = ServiceElementUtil.getMatchedPlatformCapabilities(sElem, pCaps); logger.trace("Invoke ServiceBeanExecHandler.exec for {}", ServiceLogUtil.logName(sElem)); instance = execManager.exec(opStringMgr, new JSBDiscardManager(), matched); logger.trace("ServiceBeanInstance obtained from ServiceBeanExecHandler for {}", ServiceLogUtil .logName(sElem)); serviceRecord = execManager.getServiceRecord(); logger.trace("ServiceRecord obtained from ServiceBeanExecHandler for {}", ServiceLogUtil.logName(sElem)); } catch (Exception e) { abortThrowable = e; } } else { /* Create the DiscardManager */ JSBDiscardManager discardManager = new JSBDiscardManager(); /* Create the ServiceBeanManager */ DefaultServiceBeanManager serviceBeanManager = new DefaultServiceBeanManager(sElem, opStringMgr, computeResource.getHostName(), computeResource.getAddress().getHostAddress(), container.getUuid()); serviceBeanManager.setDiscardManager(discardManager); serviceBeanManager.setServiceID(serviceID); /* * Load and start the ServiceBean */ loadResult = ServiceBeanLoader.load(sElem, serviceID, serviceBeanManager, container); org.rioproject.associations.AssociationManagement associationManagement; ClassLoader currentCL = Thread.currentThread().getContextClassLoader(); try { ClassLoader jsbCL = loadResult.getImpl().getClass().getClassLoader(); Thread.currentThread().setContextClassLoader(jsbCL); context = loadResult.getServiceBeanContext(); associationManagement = context.getAssociationManagement(); serviceProxy = loadResult.getMarshalledInstance().get(false); } finally { Thread.currentThread().setContextClassLoader(currentCL); } serviceID = loadResult.getServiceID(); /* Set properties to the ServiceCostCalculator */ serviceCostCalculator.setDownloadRecords(stagedDataManager.getDownloadRecords()); //serviceCostCalculator.setImpl(loadResult.impl); //serviceCostCalculator.setProxy(serviceProxy); serviceCostCalculator.setServiceBeanContext(context); /* Register any PlatformCapability mbeans we created for * the ServiceBean */ registerPlatformCapabilities(); if(context.getAssociationManagement() instanceof DefaultAssociationManagement) { ((DefaultAssociationManagement)context.getAssociationManagement()).setBackend(loadResult.getImpl()); ((DefaultAssociationManagement)associationManagement).setServiceBeanContainer(container); ((DefaultAssociationManagement)associationManagement).setServiceBeanContext(context); } else { logger.warn("The service's AssociationManagement is not an instance of {}, " + "failed to invoke setBackend method on [{}] impl", context.getAssociationManagement(), sElem.getName()); } if(context instanceof DefaultServiceBeanContext) { EventHandler eH = ((DefaultServiceBeanContext)context).getEventTable().get(SLAThresholdEvent.ID); if(eH!=null) { slaEventHandler = eH; logger.debug("Set EventHandler [{}] for SLAManagement for service {}", slaEventHandler.getClass().getName(), sElem.getName()); } } /* Create the ServiceBeanSLAManager */ serviceBeanSLAManager = new ServiceBeanSLAManager(loadResult.getImpl(), serviceProxy, context, slaEventHandler); serviceBeanSLAManager.addSLAs(sElem.getServiceLevelAgreements().getServiceSLAs()); serviceBeanSLAManager.createSLAThresholdEventAdapter(); sElemChangeMgr = new ServiceElementChangeManager(context, serviceBeanSLAManager, serviceProxy); context.getServiceBeanManager().addListener(sElemChangeMgr); /* Invoke postInitialize lifecycle method if defined * (RIO-141) */ BeanHelper.invokeLifeCycle(Initialized.class, "postInitialize", loadResult.getImpl()); /* Create the ServiceBeanInstance */ instance = new ServiceBeanInstance(serviceID, loadResult.getMarshalledInstance(), context.getServiceBeanConfig(), container.getComputeResource().getHostName(), container.getComputeResource().getAddress().getHostAddress(), container.getUuid()); /* Create the ServiceRecord */ serviceRecord = new ServiceRecord(serviceID, sElem, container.getComputeResource().getAddress().getHostName()); } /* If we have not aborted, continue ... */ if(abortThrowable==null) { container.started(identifier); } else { throw abortThrowable; } } catch(Throwable t) { StringBuilder buff = new StringBuilder(); String label = "classpath"; if(sElem.getComponentBundle()!=null) { if(sElem.getComponentBundle().getArtifact()==null) { String[] jars = sElem.getComponentBundle().getJARNames(); for(int i=0; i<jars.length; i++) { if(i>0) buff.append(", "); buff.append(sElem.getComponentBundle().getCodebase()).append(jars[i]); } } else { label = "artifact"; buff.append(sElem.getComponentBundle().getArtifact()); } } else { buff.append("<unknown>"); } abortThrowable = t; if(t instanceof MissingMethodException) { MissingMethodException e = (MissingMethodException)t; logger.warn("===> "+sElem.getName()+", MISSING:"+e.getMethod()); } logger.error("Failed to load the ServiceBean [{}] {} [{}]", sElem.getName(), label, buff.toString(), abortThrowable); container.discarded(identifier); terminate(); } } }; jsbThread.start(); try { jsbThread.join(); logger.trace("ServiceBean [{}] start thread completed", sElem.getName()); } catch(InterruptedException e) { logger.warn("ServiceBean [{}] start Thread interrupted, abort start", sElem.getName()); } finally { starting.set(false); } try { /* Invoke postStart lifecycle method if defined (RIO-141). Note that * we will not have a loadResult.impl of the service if it has been * forked/exec'd */ if(loadResult!=null && loadResult.getImpl()!=null) { Class<? extends Annotation> annotation = BeanHelper.hasAnnotation(loadResult.getImpl(), PostConstruct.class)? PostConstruct.class :Started.class; BeanHelper.invokeLifeCycle(annotation, "postStart", loadResult.getImpl()); } } catch (Exception e) { logger.warn("Failed to invoke the postStart() lifecycle method on the target bean. " + "At this point this is considered a non-fatal exception", e); } finally { /* Remove the initialization cookie, Make sure to check for the * context, similar to the above, we will not have a context for * the service if it has been forked/exec'd (RIO-141) */ if(context!=null) { Map<String, Object> configParms = context.getServiceBeanConfig().getConfigurationParameters(); configParms.remove(Constants.STARTING); context.getServiceBeanConfig().setConfigurationParameters(configParms); } } if(abortThrowable != null) { for(PlatformCapability pCap : installedPlatformCapabilities) { pCap.decrementUsage(); } ServiceBeanInstantiationException toThrow; if(abortThrowable instanceof ServiceBeanInstantiationException) { toThrow = (ServiceBeanInstantiationException) abortThrowable; } else { toThrow = new ServiceBeanInstantiationException(String.format("ServiceBean [%s] instantiation failed", ServiceLogUtil.logName(sElem)), abortThrowable, true); } stagedDataManager.removeInstalledPlatformCapabilities(); throw toThrow; } } /* * Get the created implementation */ public Object getImpl() { return loadResult.getImpl(); } /* * Get the service proxy */ public Object getProxy() { return serviceProxy; } public ServiceBeanLoaderResult getLoadedServiceResult() { return loadResult; } /* * Register any PlatformCapability mbeans we created for * the ServiceBean */ private void registerPlatformCapabilities() { for (PlatformCapability pCap : stagedDataManager.getInstalledPlatformCapabilities()) { try { ObjectName objectName = JMXUtil.getObjectName(context, "", "PlatformCapability", pCap.getName()); MBeanServerFactory.getMBeanServer().registerMBean(pCap, objectName); } catch (Exception e) { Throwable cause = e; if (e.getCause() != null) cause = e.getCause(); logger.warn("Registering PlatformCapability [{}] to JMX", pCap.getName(), cause); } } } /* * Unregister a PlatformCapability from JMX */ private void unregisterPlatformCapability(PlatformCapability pCap) { try { if(context==null) return; ObjectName objectName = JMXUtil.getObjectName(context, "", "PlatformCapability", pCap.getName()); MBeanServerFactory.getMBeanServer().unregisterMBean(objectName); } catch(Exception e) { logger.warn("Unregistering PlatformCapability [{}]:{}", pCap.getName(), e.toString(), e); } } /* * Set discarded attributes in the ServiceRecord */ private void setDiscarded() { /* check if the service is "starting" this may happen if service * creation is aborted before the start thread completes */ if(starting.get()) { int iterations = 0; while(serviceRecord==null && iterations<4) { try { Thread.sleep(500); } catch (InterruptedException e) { // } iterations++; } } isDiscarded.set(true); if(serviceRecord==null) { logger.warn("Discarding [{}] service, has no ServiceRecord", sElem.getName()); return; } synchronized(serviceRecordLock) { serviceRecord.setDiscardedDate(new Date()); serviceRecord.setType(ServiceRecord.INACTIVE_SERVICE_RECORD); } } private boolean runningForked() { return (System.getProperty(Constants.SERVICE_BEAN_EXEC_NAME)!=null); } /** * The JSBDiscardManager provides a mechanism to manage the discarding of a * ServiceBean */ class JSBDiscardManager implements DiscardManager, LifeCycle { /** * @see org.rioproject.impl.container.DiscardManager#discard */ public void discard() { if(terminated.get()) return; setDiscarded(); container.discarded(identifier); instance=null; terminate(); } /** * @see com.sun.jini.start.LifeCycle#unregister */ public boolean unregister(Object impl) { discard(); return(true); } } }