Package org.rioproject.impl.associations.strategy

Source Code of org.rioproject.impl.associations.strategy.Utilization$ServiceCapability

/*
* Copyright 2008 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.impl.associations.strategy;

import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceItem;
import net.jini.id.ReferentUuid;
import net.jini.id.Uuid;
import net.jini.id.UuidFactory;
import org.rioproject.associations.Association;
import org.rioproject.associations.AssociationDescriptor;
import org.rioproject.deploy.DeployedService;
import org.rioproject.deploy.DeploymentMap;
import org.rioproject.deploy.ServiceBeanInstance;
import org.rioproject.entry.OperationalStringEntry;
import org.rioproject.opstring.ClassBundle;
import org.rioproject.impl.opstring.OpStringManagerProxy;
import org.rioproject.opstring.OperationalStringManager;
import org.rioproject.opstring.ServiceElement;
import org.rioproject.sla.SLA;
import org.rioproject.system.ComputeResourceUtilization;
import org.rioproject.system.MeasuredResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
* A round-robin selector that selects services running on compute resources
* whose system resources are not depleted. System resource depletion is
* determined by {@link org.rioproject.system.MeasuredResource} provided as part of
* the {@link org.rioproject.system.ResourceCapability} object returned as part
* of the deployment map.
*
* @author Dennis Reedy
*/
public class Utilization<T> extends AbstractServiceSelectionStrategy<T> {
    private SLA sla;
    private final List<ServiceCapability<T>> services = Collections.synchronizedList(new ArrayList<ServiceCapability<T>>());
    private OperationalStringManager opMgr;
    /** Scheduler for Cybernode utilization gathering */
    private ScheduledExecutorService scheduler;
    private static Logger logger = LoggerFactory.getLogger(Utilization.class.getName());

    @Override
    public void setAssociation(final Association<T> association) {
        this.association = association;
        initialize(association.getOperationalStringName());
    }

    @SuppressWarnings("unused")
    public void setSLA(final SLA sla) {
        this.sla = sla;
    }

    public T getService() {
        T service = null;
        ServiceCapability<T> selected = null;
        /*  Round-Robin */
        for(ServiceCapability<T> sc : getServices()) {
            if(sc==null)
                continue;
            if(sc.isInvokable()) {
                services.remove(sc);
                services.add(sc);
                selected = sc;
                service = sc.getService();
                break;
            }
        }
        if(logger.isTraceEnabled()) {
            String name = association==null?"<unknown>":association.getName();
            if(selected!=null) {
                String address = selected.cru==null?"<unknown>":selected.cru.getAddress();
                String util = selected.cru==null?"<unknown>":selected.cru.getUtilization().toString();
                logger.trace("Using associated service [{}] at Host address={}, Utilization={}, values={}",
                             name, address, util, selected.getMeasuredResourcesAsList().toString());
            } else {
                logger.trace("All services are either breached, or none are available for associated service [{}]", name);
            }
        }
        return service;
    }

    @Override
    public void serviceAdded(final T service) {
        logger.trace("Adding service for {}, {}", association.getName(), service);
        ServiceItem item = association.getServiceItem(service);
        logger.trace("Found ServiceItem?, {}", item);
        if(item!=null) {
            addService(item);
        } else {
            logger.warn("Unable to obtain ServiceItem for {}, force refresh all service instances", service.toString());
            services.clear();
            for(ServiceItem serviceItem : association.getServiceItems())
                addService(serviceItem);
        }
    }

    @Override
    public void serviceRemoved(final T service) {
        if(removeService(service)){
            logger.debug("Service removed, service collection size={}", services.size());
        }
    }

    @Override
    public void terminate() {       
        if(scheduler!=null) {
            scheduler.shutdownNow();
        }
        if(opMgr!=null) {
            try {
                ((OpStringManagerProxy.OpStringManager)opMgr).terminate();
            } catch(IllegalStateException e) {
                logger.warn("Terminating the Utilization strategy for associated service {}", association.getName(), e);
            }
        }
    }

    private void initialize(final String opStringName) {
        String opStringNameToUse = opStringName;
        if(opStringNameToUse==null) {
            ServiceItem item = association.getServiceItem();
            if(item==null)
                return;
            for(Entry e : item.attributeSets) {
                if(e instanceof OperationalStringEntry) {
                    opStringNameToUse = ((OperationalStringEntry)e).name;
                    break;
                }
            }
        }
        if(opStringNameToUse!=null && opMgr==null && association.getServiceItem()!=null) {
            try {
                opMgr = OpStringManagerProxy.getProxy(opStringNameToUse, null);
                ComputeResourceUtilizationFetcher cruf = new ComputeResourceUtilizationFetcher(opMgr,
                                                                                               opStringNameToUse);
                setServiceList(association.getServiceItems());
                long initialDelay = 0;
                long period = 1000*5;               
                scheduler = Executors.newSingleThreadScheduledExecutor();
                scheduler.scheduleAtFixedRate(cruf, initialDelay, period, TimeUnit.MILLISECONDS);
                logger.trace("Initialized");
            } catch (RemoteException e) {
                logger.warn("Getting ServiceElement for [{}]", association.getName(), e);
            } catch (Exception e) {
                logger.warn("Unable to create OpStringManagerProxy for associated service [{}]", association.getName(), e);
            }
        } else {
            logger.warn("Unable to initialize successfully. opStringNameToUse: {}, opMgr: {}, association.getServiceItem(): {}",
                        opStringNameToUse, opMgr, association.getServiceItem());
        }
    }

    private void setServiceList(final ServiceItem[] items) {
        services.clear();
        for(ServiceItem item : items) {
            addService(item);
        }
    }

    @SuppressWarnings("unchecked")
    private synchronized void addService(final ServiceItem item) {
        if(opMgr==null) {
            String opStringName = null;
            for(Entry e : item.attributeSets) {
                if(e instanceof OperationalStringEntry) {
                    opStringName = ((OperationalStringEntry)e).name;
                    break;
                }
            }
            initialize(opStringName);
        }
        Uuid uuid;
        if(item.service instanceof ReferentUuid)
            uuid = ((ReferentUuid)item.service).getReferentUuid();
        else {
            uuid = UuidFactory.create(item.serviceID.getMostSignificantBits(),
                                      item.serviceID.getLeastSignificantBits());
        }

        boolean alreadyHaveIt = false;
        for(ServiceCapability<T> sc : services) {
            if(sc.uuid.equals(uuid)) {
                alreadyHaveIt = true;
                break;
            }
        }

        if(!alreadyHaveIt) {
            services.add(new ServiceCapability(item.service, uuid));
            logger.trace("Adding new ServiceCapability, service count now {}", services.size());
        } else {
            logger.trace("Already have {}, service count now {}", item, services.size());
        }
    }

    private boolean removeService(final T service) {
        boolean removed = false;
        for(ServiceCapability sc : getServices()) {
            if(sc.getService().equals(service)) {
                removed = services.remove(sc);
            }
        }
        return removed;
    }

    @SuppressWarnings("unchecked")
    private ServiceCapability<T>[] getServices() {
        return services.toArray(new ServiceCapability[services.size()]);
    }

    class ComputeResourceUtilizationFetcher implements Runnable {
        final OperationalStringManager opMgr;
        final String opStringName;
        final List<DeployedService> list = new ArrayList<DeployedService>();
        final List<ServiceElement> serviceElements = new ArrayList<ServiceElement>();

        ComputeResourceUtilizationFetcher(final OperationalStringManager opMgr,
                                          final String opStringName) {
            this.opMgr = opMgr;
            this.opStringName = opStringName;
        }

        public void run() {
            list.clear();
            try {
                logger.trace("ComputeResourceUtilizationFetcher, obtaining DeploymentMap for [{}]", opStringName);
                DeploymentMap dMap = opMgr.getDeploymentMap();
                if(serviceElements.isEmpty()) {
                    serviceElements.addAll(getMatchingServiceElements(dMap));
                    if(serviceElements.isEmpty())
                        logger.warn("Unable to obtain matching ServiceElement(s) for associated service [{}]",
                                    association.getName());
                }
                if(dMap!=null) {
                    for(ServiceElement elem : serviceElements)
                        list.addAll(dMap.getDeployedServices(elem));
                }
            } catch (RemoteException e) {
                logger.warn("Getting utilization for service [{}], terminating", association.getAssociationDescriptor(), e);
                terminate();
            }
            for(DeployedService deployed : list) {
                ServiceBeanInstance sbi = deployed.getServiceBeanInstance();
                ComputeResourceUtilization cru =
                    deployed.getComputeResourceUtilization();
                for(ServiceCapability sc : services) {
                    if(sc.uuid.equals(sbi.getServiceBeanID())) {
                        logger.trace("Obtained ComputeResourceUtilization for [{}]", association.getName());
                        sc.setComputeResourceUtilization(cru);
                        break;
                    }
                }
            }
        }

        private List<ServiceElement> getMatchingServiceElements(final DeploymentMap dMap) {
            List<ServiceElement> matching = new ArrayList<ServiceElement>();
            AssociationDescriptor ad = association.getAssociationDescriptor();
            String[] adInterfaces = ad.getInterfaceNames();
            Arrays.sort(adInterfaces);
            for(ServiceElement elem : dMap.getServiceElements()) {
                List<String> list = new ArrayList<String>();
                for(ClassBundle cb : elem.getExportBundles()) {
                    list.add(cb.getClassName());
                }
                String[] cbInterfaces = list.toArray(new String[list.size()]);
                if(Arrays.equals(adInterfaces, cbInterfaces)) {
                    if(ad.matchOnName()) {
                        if(ad.getName().equals(elem.getName())) {
                            matching.add(elem);
                        }
                    } else {
                        matching.add(elem);
                    }
                }
            }
            return matching;
        }
    }

    class ServiceCapability<T> {
        final T service;
        final Uuid uuid;
        ComputeResourceUtilization cru;
        boolean wasBreached = false;
        final Object updateLock = new Object();

        ServiceCapability(final T service, final Uuid uuid) {
            this.service = service;
            this.uuid = uuid;
        }

        T getService() {
            return service;
        }

        void setComputeResourceUtilization(final ComputeResourceUtilization cru) {
            synchronized(updateLock) {
                this.cru = cru;
            }
        }

        List<MeasuredResource> getMeasuredResourcesAsList() {
            List<MeasuredResource> list = new ArrayList<MeasuredResource>();
            if(cru!=null) {
                synchronized(updateLock) {
                    list.addAll(cru.getMeasuredResources());
                }
            }
            return list;
        }

        boolean isInvokable() {
            boolean isInvokable;
            synchronized(updateLock) {
                isInvokable = (cru == null || cru.measuredResourcesWithinRange());
                if(cru !=null) {
                    if(isInvokable) {
                        for(MeasuredResource mRes : cru.getMeasuredResources()) {
                            if(sla!=null &&
                               sla.getIdentifier().equals(mRes.getIdentifier())) {
                                isInvokable = mRes.evaluate(sla);
                                break;
                            }
                        }

                    } else {
                        if(logger.isDebugEnabled()) {
                            List<MeasuredResource> breached = new ArrayList<MeasuredResource>();
                            for(MeasuredResource mRes : cru.getMeasuredResources()) {
                                if(mRes.thresholdCrossed()) {
                                    breached.add(mRes);
                                }
                            }
                            logger.debug("Associated service at Host address={}, Utilization={} has breached resources: {}",
                                         cru.getAddress(), cru.getUtilization(), breached.toString());
                        }
                    }
                    if(isInvokable && wasBreached) {
                        logger.debug("Associated service at Host address={}, Utilization={} was breached, now invokable",
                                     cru.getAddress(), cru.getUtilization());
                    }
                }
            }
            wasBreached = !isInvokable;

            return isInvokable;
        }
    }
}
TOP

Related Classes of org.rioproject.impl.associations.strategy.Utilization$ServiceCapability

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.