Package org.rioproject.impl.service

Source Code of org.rioproject.impl.service.ResourceLessor$LeaseReaper

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

import com.sun.jini.landlord.LeasedResource;
import net.jini.core.lease.Lease;
import net.jini.core.lease.LeaseDeniedException;
import net.jini.id.Uuid;
import org.rioproject.impl.util.TimeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

/**
* Abstract class to manage the service's leased resources.
*
* @author Dennis Reedy
*/
@SuppressWarnings("unused")
public abstract class ResourceLessor {
    /** A hash of resources to cookies */
    private final Map<Uuid, LeasedResource> resources = new ConcurrentHashMap<Uuid, LeasedResource>();
    /** A Thread which will clean up stale leases */
    private Thread reaper = null;
    private long reapingInterval = TimeConstants.ONE_SECOND*10;
    /** A LinkedList of LeaseListener objects */
    private final List<LeaseListener> listeners = new LinkedList<LeaseListener>();
    /** Component for getting the Logger */
    private static final String COMPONENT_NAME = ResourceLessor.class.getPackage().getName();
    /** The Logger */
    private static final Logger logger = LoggerFactory.getLogger(ResourceLessor.class);

    /**
     * Check to make sure that the LeasedResource lease has not expired yet <br>
     *
     * @param resource The LeasedResource
     *
     * @return Returns true if the lease on the passed resource has not expired
     * yet
     */
    public boolean ensure(final LeasedResource resource) {
        return(resource.getExpiration() > currentTime());
    }

    public void setReapingInterval(long reapingInterval) {
        this.reapingInterval = reapingInterval;
    }

    /**
     * Create a new lease <br>
     *
     * @param resource to be leased
     * @param duration Time requested for <code>Lease</code>
     *
     * @throws LeaseDeniedException If the lease has been denied
     * @return A new Lease
     */
    public abstract Lease newLease(LeasedResource resource, long duration) throws LeaseDeniedException;

    /**
     * Remove a leased resource from the list of managed leases. <br>
     *
     * @param resource ServiceResource to remove
     *
     * @return true if the lease was removed
     */
    public boolean remove(final LeasedResource resource) {
        return (remove(resource.getCookie()));
    }

    /**
     * Remove all leased resources .<br>
     */
    public void removeAll() {
        LeasedResource[] resources = getLeasedResources();
        for (LeasedResource resource : resources) {
            remove(resource.getCookie());
        }
    }

    /**
     * Remove a leased resource from the list of managed leases. <br>
     *
     * @param cookie Object to remove
     *
     * @return boolean True if removed false if not removed
     */
    public boolean remove(final Uuid cookie) {
        LeasedResource resource;
        boolean removed = false;
        synchronized(resources) {
            resource = resources.remove(cookie);
        }
        if(resource != null) {
            notifyLeaseRemoval(resource);
            removed = true;
        }
        return (removed);
    }

    /**
     * Add a LeaseListener <br>
     *
     * @param listener the LeaseListener to add
     */
    public void addLeaseListener(final LeaseListener listener) {
        listeners.add(listener);
    }

    /**
     * Remove a LeaseListener <br>
     *
     * @param listener the LeaseListener to remove
     */
    public void removeLeaseListener(final LeaseListener listener) {
        listeners.remove(listener);
    }

    /**
     * @return the total number of service resources that have been leased
     */
    public int total() {
        int size;
        synchronized(resources) {
            size = resources.size();
        }
        return (size);
    }

    /**
     * Add a LeasedResource for a new Lease or renewing a Lease
     *
     * @param resource The resource to add or update
     *
     * @throws IllegalArgumentException if the resource is null
     */
    public void addLeasedResource(final LeasedResource resource) {
        if(resource == null)
            throw new IllegalArgumentException("resource is null");
        synchronized(this) {
            if(reaper==null) {
                reaper = new LeaseReaper(reapingInterval);
                reaper.setDaemon(true);
                reaper.start();
            }
        }
        synchronized(resources) {
            resources.put(resource.getCookie(), resource);
        }
    }

    /**
     * Get a LeasedResource
     *
     * @param cookie The Uuid of the LeasedResource to get
     *
     * @return The LeasedResource for the Uuid
     *
     * @throws IllegalArgumentException if the cookie is null
     */
    public LeasedResource getLeasedResource(final Uuid cookie) {
        if(cookie == null)
            throw new IllegalArgumentException("cookie is null");
        LeasedResource resource;
        synchronized(resources) {
            resource = resources.get(cookie);
        }
        return(resource);
    }
    /**
     * This method returns a snapshot of the LeasedResource objects that
     * this ResourceLessor is managing
     *
     * @return An array of LeasedResource elements. If no LeasedResource
     * objects are found return a zero-length array. A new array is returned
     * each time
     */
    public LeasedResource[] getLeasedResources() {
        LeasedResource[] leasedResources;
        synchronized(resources) {
            Collection<LeasedResource> c = resources.values();
            leasedResources = c.toArray(new LeasedResource[c.size()]);
        }
        if(logger.isTraceEnabled())
            logger.trace("Number of resources: {}, returned: {}", resources.size(), leasedResources.length);
        return (leasedResources);
    }

    /**
     * Notify LeaseListener instances of a new registration
     *
     * @param resource The LeasedResource
     */
    public void notifyLeaseRegistration(final LeasedResource resource) {
        for (LeaseListener listener : listeners)
            listener.register(resource);
    }

    /**
     * Notify LeaseListener instances of a lease renewal
     *
     * @param resource The LeasedResource
     */
    public void notifyLeaseRenewal(final LeasedResource resource) {
        for (LeaseListener listener : listeners)
            listener.renewed(resource);
    }

    /**
     * Notify LeaseListener instances of a lease expiration
     *
     * @param resource The LeasedResource
     */
    public void notifyLeaseExpiration(final LeasedResource resource) {
        for (LeaseListener listener : listeners)
            listener.expired(resource);
    }

    /**
     * Notify LeaseListener instances of a lease removal
     *
     * @param resource The LeasedResource
     */
    public void notifyLeaseRemoval(final LeasedResource resource) {
        for (LeaseListener listener : listeners)
            listener.removed(resource);
    }

    /**
     * Stop and clean up all resources
     */
    public void stop() {
        if(reaper!=null)
            reaper.interrupt();
        reaper = null;
        removeAll();
    }

    /**
     * Method that provides some notion of the current time in milliseconds
     * since the beginning of the epoch. Default implementation calls
     * System.currentTimeMillis()
     *
     * @return The current time
     */
    public long currentTime() {
        return (System.currentTimeMillis());
    }
   
    /**
     * Clean up leases that have not been renewed. Check every 30 seconds for
     * stale leases
     */
    protected class LeaseReaper extends Thread {
        private final long reapingInterval;

        public LeaseReaper(long reapingInterval) {
            super("LeaseReaper");
            this.reapingInterval = reapingInterval;
        }
       
        public void run() {
            while (reaper != null || !isInterrupted()) {
                try {
                    Thread.sleep(reapingInterval);
                } catch(InterruptedException e) {
                    break;
                }
                Set<Entry<Uuid,LeasedResource>> mapEntries;
                synchronized(resources) {
                    mapEntries = resources.entrySet();
                }
                for (Entry<Uuid, LeasedResource> entry : mapEntries) {
                    LeasedResource lr = entry.getValue();
                    if (!ensure(lr)) {
                        if (logger.isDebugEnabled())
                            logger.debug("Lease expired for resource {}, cookie {}",
                                         ((ServiceResource) lr).getResource().toString(), lr.getCookie());
                        remove(lr.getCookie());
                        notifyLeaseExpiration(lr);
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.rioproject.impl.service.ResourceLessor$LeaseReaper

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.