/* * Copyright 2008 the original author or authors. * Copyright 2005 Sun Microsystems, Inc. * * 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.impl.system.measurable; import com.sun.jini.config.Config; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import org.rioproject.costmodel.ResourceCost; import org.rioproject.costmodel.ResourceCostModel; import org.rioproject.costmodel.ResourceCostProducer; import org.rioproject.costmodel.ZeroCostModel; import org.rioproject.impl.watch.PeriodicWatch; import org.rioproject.impl.watch.ThresholdManager; import org.rioproject.sla.SLA; import org.rioproject.system.MeasuredResource; import org.rioproject.watch.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; /** * A MeasurableCapability refers to a depletion oriented resource or capability on * a ComputeResource * * @author Dennis Reedy */ public abstract class MeasurableCapability extends PeriodicWatch implements ResourceCostProducer, MeasurableCapabilityMBean { /** * Collection of secondary ThresholdManager instances */ private final Collection<ThresholdManager> thresholdManagers = new ArrayList<ThresholdManager>(); /** * The SLA for the MeasurableCapability */ private SLA sla; /** * The ResourceCostModel, determining how to charge for use of the * MeasurableCapability */ private ResourceCostModel costModel; /** * The sampleSize property specifies the amount of samples the * MeasurableCapability will accumulate in the period defined by the reportRate * in order to produce a result. */ protected int sampleSize = 1; /** Whether or not this measurable capability is enabled */ private AtomicBoolean isEnabled = new AtomicBoolean(true); /** The {@link MeasurableMonitor} to use */ protected MeasurableMonitor monitor; protected MeasuredResource lastMeasured; /** Defines the default history size */ public final static int DEFAULT_COLLECTION_SIZE = 10; /** Defines the default history max size */ public final static int MAX_COLLECTION_SIZE = 100; private int collectionSize; private static final Logger logger = LoggerFactory.getLogger(MeasurableCapability.class); protected MeasurableCapability(final String id, final String componentName, final Configuration config) { super(id, config); try { isEnabled.set((Boolean) config.getEntry(componentName, "enabled", boolean.class, Boolean.TRUE)); } catch (ConfigurationException e) { logger.error("Getting WatchDataSource Size", e); } if(!isEnabled.get()) return; try { collectionSize = Config.getIntEntry(config, componentName, "collectionSize", DEFAULT_COLLECTION_SIZE, 1, MAX_COLLECTION_SIZE); } catch(ConfigurationException e) { if(logger.isTraceEnabled()) logger.trace("Getting WatchDataSource collection size", e); collectionSize = DEFAULT_COLLECTION_SIZE; } try { WatchDataSource wds = (WatchDataSource)config.getEntry(componentName, "watchDataSource", WatchDataSource.class, null); if(wds!=null) { doSetWatchDataSource(wds); } } catch (ConfigurationException e) { logger.error("Getting WatchDataSource Size", e); } if(localRef!=null) localRef.setMaxSize(collectionSize); } public void addWatchDataReplicator(WatchDataReplicator replicator) { if(localRef!=null) { localRef.addWatchDataReplicator(replicator); } else { try { watchDataSource.addWatchDataReplicator(replicator); } catch (RemoteException e) { logger.error("Could not add WatchDataReplicator", e); } } } protected void setEnabled(boolean enabled) { this.isEnabled.set(enabled); } /** * Get is this measurable capability is enabled * * @return If the measurable capability is enabled return true, otherwise * false. If the measurable capability is not enabled, it will not be added */ public boolean isEnabled() { return isEnabled.get(); } private void checkEnabled() { if(!isEnabled.get()) throw new IllegalStateException("The MeasurableCapability ["+getId()+"] is not enabled"); } /** * Override parent's setWatchDataSource to set the size */ @Override public void setWatchDataSource(WatchDataSource watchDataSource) { doSetWatchDataSource(watchDataSource); } private void doSetWatchDataSource(WatchDataSource watchDataSource) { checkEnabled(); super.setWatchDataSource(watchDataSource); if(watchDataSource!=null) { try { watchDataSource.setMaxSize(collectionSize); } catch(Exception e) { logger.error("Setting WatchDataSource Size", e); } } } /** * Set the SLA for ths MeasurableCapability. * * @param sla The SLA for this MeasurableCapability */ public void setSLA(SLA sla) { checkEnabled(); if(sla == null) throw new IllegalArgumentException("sla is null"); this.sla = sla; getThresholdManager().setThresholdValues(sla); } /** * Get the SLA for ths MeasurableCapability. * * @return The SLA for this MeasurableCapability */ public SLA getSLA() { return(sla); } /** * @see MeasurableCapabilityMBean#setSampleSize */ public void setSampleSize(int sampleSize) { checkEnabled(); this.sampleSize = sampleSize; } /** * @see MeasurableCapabilityMBean#getSampleSize() */ public int getSampleSize() { return(sampleSize); } /** * Add a secondary ThresholdManager to the MeasurableCapability. The primary * ThresholdManager and the ThresholdValues are set when this class is loaded. * By offering secondary ThresholdManager instances, services can set their own * ranges and be notified accordingly * * @param thresholdManager The ThresholdManager */ public void addSecondaryThresholdManager(ThresholdManager thresholdManager) { checkEnabled(); if(thresholdManager==null) throw new IllegalArgumentException("thresholdManager is null"); thresholdManagers.add(thresholdManager); } /** * Remove a secondary ThresholdManager from the MeasurableCapability * * @param thresholdManager The ThresholdManager */ public void removeSecondaryThresholdManager(ThresholdManager thresholdManager) { if(thresholdManager!=null) thresholdManagers.remove(thresholdManager); } /** * Set the ResourceCostModel for the MeasurableCapability * * @param costModel The ResourceCostModel which will determine the cost of * using this MeasurableCapability */ public void setResourceCostModel(ResourceCostModel costModel) { checkEnabled(); if(costModel==null) throw new IllegalArgumentException("costModel is null"); this.costModel = costModel; } /** * @see org.rioproject.costmodel.ResourceCostProducer#calculateResourceCost */ public ResourceCost calculateResourceCost(double units, long duration) { checkEnabled(); if(costModel==null) costModel = new ZeroCostModel(); double cost = costModel.getCostPerUnit(duration)*units; return(new ResourceCost(getId(), cost, units, costModel.getDescription(), new Date(System.currentTimeMillis()))); } /** * Get the MeasuredResource object, which represents this object's measured * capability * * @return This object's measured capability */ public MeasuredResource getMeasuredResource() { checkEnabled(); if(lastMeasured==null) checkValue(); return lastMeasured; } protected void setLastMeasuredResource(MeasuredResource lastMeasured) { this.lastMeasured = lastMeasured; } /** * Set the {@link MeasurableMonitor} * * @param monitor The MeasurableMonitor */ public void setMeasurableMonitor(MeasurableMonitor monitor) { this.monitor = monitor; this.monitor.setID(getId()); this.monitor.setThresholdValues(getThresholdValues()); } /** * Add a Calculable to the watch and update state * * @param record A Calculable record */ public void addWatchRecord(Calculable record) { checkEnabled(); super.addWatchRecord(record); for (ThresholdManager tManager : getThresholdManagers()) tManager.checkThreshold(record); } /** * Get the registered {@link ThresholdManager}s * * @return The registered {@link ThresholdManager}s. A new unmodifiable collection is allocated each time */ protected Collection<ThresholdManager> getThresholdManagers() { Collection<ThresholdManager> tMgrs; synchronized(thresholdManagers) { tMgrs = Collections.unmodifiableCollection(thresholdManagers); } return tMgrs; } }