Package org.rioproject.monitor.service.managers

Source Code of org.rioproject.monitor.service.managers.PendingServiceElementManager

/*
* 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.managers;

import org.rioproject.deploy.ServiceProvisionListener;
import org.rioproject.impl.servicebean.ServiceElementUtil;
import org.rioproject.monitor.service.ProvisionRequest;
import org.rioproject.monitor.service.util.LoggingUtil;
import org.rioproject.opstring.ServiceElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
* Abstract class which will manage ProvisionRequest instances that are waiting
* to be provisioned. There are two types of ServiceElements which require
* management:
* <ol>
* <li>ServiceElement objects which could not be provisioned and need to be put
* on a pending list. These elements have the provision type of DYNAMIC, and
* will be provisioned when instantiation resources become available that meet
* their operational requirements
* <li>ServiceElement objects that will be provisioned to all instantiation
* resources that match their operational requirements. These elements have the
* provision type of FIXED
* </ol>
*
* @author Dennis Reedy
*/
public abstract class PendingServiceElementManager {
    /** Sorted collection of pending provision requests */
    protected final TreeMap<Key, ProvisionRequest> collection;
    /** Index into the collection to insert elements */
    private long collectionIndex = 1;
    /** A descriptive String type */
    private final String type;
    /** A Logger */
    private final Logger logger = LoggerFactory.getLogger(PendingServiceElementManager.class.getName());

    /**
     * A key for the sortable set
     */
    static class Key implements Comparable {
        int priority;
        ServiceElement sElem;
        long index;
        long timestamp;
       
        Key(ServiceElement sElem, long index, long timestamp) {
            this.sElem = sElem;
            this.index = index;
            this.timestamp = timestamp;
        }
       
        /*
         * @see java.lang.Comparable#compareTo(java.lang.Object)
         */
        public int compareTo(Object o) {
            if(!(o instanceof Key))
                throw new ClassCastException();
            if(this==o)
                return(0);
            Key that = (Key)o;
            int comparison;
            long now = System.currentTimeMillis();
            /* The priority is the high order bit, if not set then check if
             * the ServiceElement objects are equal, if they are, make sure
             * instanceIDs are sorted. If the ServiceElement instances dont match,
             * compare on the timestamp, then the index */
            if(this.priority==0 && that.priority==0) {
                if(this.sElem.equals(that.sElem)) {
                    Long thisInstanceID = this.sElem.getServiceBeanConfig().getInstanceID();
                    Long thatInstanceID = that.sElem.getServiceBeanConfig().getInstanceID();
                    comparison = thisInstanceID.compareTo(thatInstanceID);
                } else {
                    /* Dont have different timestamps, use index */
                    if(this.timestamp == that.timestamp) {
                        comparison = (this.index>that.index ? 1 : -1);
                    } else {
                        /* age before beauty :) */
                        comparison = (( (now-this.timestamp) > (now-that.timestamp)) ?-1 : 1);
                    }
                }
            } else {
                /* Priority based comparison, a higher the priority comes before
                 * a lower one */
                comparison = (this.priority>that.priority ? -1 : 1);
            }
            return(comparison);
        }       
    }
   
    /**
     * Create a PendingServiceElementManager
     *
     * @param type A descriptive name for the Manager
     */

    PendingServiceElementManager(String type) {
        collection = new TreeMap<Key, ProvisionRequest>(new Comparator<Key>() {
                public int compare(Key key1, Key key2) {
                    return (key1).compareTo(key2);
                }
        });
        this.type = type;
    }

    /**
     * @return The descriptive type of this Manager
     */
    public String getType() {
        return (type);
    }

    /**
     * Add an element to the pending collection with an index
     *
     * @param request The ProvisionRequest
     * @param index The index of the ServiceElement
     * @return The index that was used to insert the ProvisionRequest into the
     * collection
     */
    public long addProvisionRequest(ProvisionRequest request, long index) {
        long ndx;
        synchronized(collection) {                       
            Long keyIndex = (index == 0 ? collectionIndex++ : index);
            Key key = new Key(request.getServiceElement(), keyIndex, request.getTimestamp());
            collection.put(key, request);
            ndx = keyIndex;
        }
        return (ndx);
    }

    /**
     * Get the size of the collection
     *
     * @return The size of the collection
     */
    int getSize() {
        int size;
        synchronized(collection) {
            size = collection.size();
        }
        return (size);
    }

    /**
     * Get the number of ServiceElement instances in the collection that match
     * provided ServiceElement
     *
     * @param sElem The ServiceElement to match
     *
     * @return The number of ServiceElement matches
     */
    int getCount(ServiceElement sElem) {
        int count = 0;
        synchronized(collection) {
            Collection<ProvisionRequest> provisionRequests = collection.values();
            for (ProvisionRequest pr : provisionRequests) {
                if (pr.getServiceElement().equals(sElem)) {
                    count++;
                }
            }
        }
        return (count);
    }

    /**
     * Remove all ServiceElement instances from the collection
     *
     * @param sElem The ServiceElement
     * @param numToRemove The number to remove
     *
     * @return An array of ProvisionRequest instances that have been removed. If
     * there are no instances that have been removed, return an empty array
     */
    public ProvisionRequest[] removeServiceElement(ServiceElement sElem, int numToRemove) {
        List<Key> removals = new ArrayList<Key>();
        List<ProvisionRequest> removed = new ArrayList<ProvisionRequest>();
       
        synchronized(collection) {
            Set<Key> keys = collection.keySet();
            for (Key key : keys) {
                ProvisionRequest pr = collection.get(key);
                if (pr != null && sElem.equals(pr.getServiceElement()))
                    removals.add(key);
            }
        }
        if(!removals.isEmpty()) {
            if(removals.size()>numToRemove) {
                removals = removals.subList((removals.size()-numToRemove),
                                            removals.size());                               
            }
            logger.info("{}: removing [{}] [{}] instances", type, removals.size(), LoggingUtil.getLoggingName(sElem));
            synchronized(collection) {
                for (Key removal : removals) {
                    ProvisionRequest pr = collection.remove(removal);
                    removed.add(pr);
                }
            }
        }
        return (removed.toArray(new ProvisionRequest[removed.size()]));
    }
   
    /**
     * Remove all ServiceElement instances from the collection
     *
     * @param sElem The ServiceElement
     *
     * @return An array of ProvisionRequest instances that have been removed. If
     * there are no instances that have been removed, return an empty array
     */
    public ProvisionRequest[] removeServiceElement(ServiceElement sElem) {
        List<Key> removals = new ArrayList<Key>();
        List<ProvisionRequest> removed = new ArrayList<ProvisionRequest>();
       
        synchronized(collection) {
            Set<Key> keys = collection.keySet();
            for (Key key : keys) {
                ProvisionRequest pr = collection.get(key);
                if (pr != null && sElem.equals(pr.getServiceElement()))
                    removals.add(key);
            }
        }
        if(!removals.isEmpty()) {
            logger.debug("{}: removing [{}] [{}] instances", type, removals.size(), LoggingUtil.getLoggingName(sElem));
            synchronized(collection) {
                for (Key removal : removals) {
                    ProvisionRequest pr = collection.remove(removal);
                    removed.add(pr);
                }
            }
        } else {
            logger.debug("{}: There are no pending instances of [{}] to remove ", type, LoggingUtil.getLoggingName(sElem));
        }
        return (removed.toArray(new ProvisionRequest[removed.size()]));
    }

    /**
     * Determine if the ServiceElement is in the collection
     *
     * @param sElem The ServiceElement
     *
     * @return If found return true
     */
    public boolean hasServiceElement(ServiceElement sElem) {
        boolean contains = false;
        synchronized(collection) {
            Set<Key> keys = collection.keySet();
            for (Key key : keys) {
                ProvisionRequest pr = collection.get(key);
                if (sElem.equals(pr.getServiceElement())) {
                    contains = true;
                    break;
                }
            }
        }
        return (contains);
    }

    /**
     * For each ProvisionRequest in the Collection of ProvisionRequest instances,
     * which contain the ServiceElement, update the ProvisionRequest with the
     * provided ServiceElement
     *
     * @param sElem The ServiceElement
     * @param listener A ServiceProvisionListener to be notified
     */
    public void updateProvisionRequests(ServiceElement sElem,
                                        ServiceProvisionListener listener) {
        synchronized(collection) {
            Set<Key> keys = collection.keySet();
            for (Key key : keys) {
                ProvisionRequest pr = collection.get(key);
                if (sElem.equals(pr.getServiceElement())) {
                    /* Preserve instance IDs */
                    Long id = pr.getServiceElement().getServiceBeanConfig().getInstanceID();
                    ServiceElement newElem = sElem;
                    if (id != null)
                        newElem = ServiceElementUtil.prepareInstanceID(sElem, id.intValue());
                    pr.setServiceElement(newElem);
                    if(listener!=null) {
                        pr.setServiceProvisionListener(listener);
                    }
                }
            }
        }
    }

    /**
     * A concrete implementation on how to process the collection is required as
     * follows: The collection will be processed, attempting to have each
     * ServiceElement provisioned to available ServiceInstantiation resources.
     * Each element will be processed with it's ordinal index ensuring that if
     * there are no available resources it will be put back into the collection
     * in order
     */
    public abstract void process();

    /**
     * Get all ProvisionRequest instances
     *
     * @param sElem The ServiceElement to use
     *
     * @return An array of ProvisionRequest instances
     */
    ProvisionRequest[] getProvisionRequests(ServiceElement sElem) {
        ProvisionRequest[] prs;       
        synchronized(collection) {           
            /* Get all ProvisionRequest instances */
            if(sElem==null) {
                Collection<ProvisionRequest> c = collection.values();
                prs = c.toArray(new ProvisionRequest[c.size()]);
            } else {
                /* Get the ProvisionRequest instances for a ServiceElement */
                ArrayList<ProvisionRequest> items = new ArrayList<ProvisionRequest>();
                Set<Key> keys = collection.keySet();
                for (Key key : keys) {
                    ProvisionRequest pr = collection.get(key);
                    if (sElem.equals(pr.getServiceElement())) {
                        items.add(pr);
                    }
                }
                prs = items.toArray(new ProvisionRequest[items.size()]);
            }
        }
        return(prs);
    }
   
    /**
     * Dumps the contents of the collection
     */
    public void dumpCollection() {
        if(logger.isTraceEnabled()) {
            ProvisionRequest[] elements = getProvisionRequests(null);
            StringBuilder buffer = new StringBuilder();
            int x=1;
            buffer.append("\n");
            buffer.append(type);
            buffer.append(" collection size : ");
            buffer.append(elements.length).append("\n");
            buffer.append("--\n");
            for (ProvisionRequest element : elements) {
                ServiceElement sElem = element.getServiceElement();
                Long id = sElem.getServiceBeanConfig().getInstanceID();
                buffer.append(x++);
                buffer.append(" ");
                buffer.append(sElem.getOperationalStringName());
                buffer.append("/");
                buffer.append(sElem.getName());
                if(!type.startsWith("Fixed")) {
                    buffer.append(" instanceID=");
                    buffer.append(id);
                }
                buffer.append("\n");
            }
            buffer.append("--");
            logger.trace(buffer.toString());
        }
    }
}
TOP

Related Classes of org.rioproject.monitor.service.managers.PendingServiceElementManager

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.