Package org.jboss.internal.soa.esb.services.registry

Source Code of org.jboss.internal.soa.esb.services.registry.CachingRegistryInterceptor$ServiceInfo

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.internal.soa.esb.services.registry;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.collections.map.LRUMap;
import org.apache.log4j.Logger;
import org.jboss.soa.esb.Service;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.common.Configuration;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.services.registry.AbstractRegistryInterceptor;
import org.jboss.soa.esb.services.registry.RegistryException;
import org.jboss.soa.esb.services.registry.ServiceNotFoundException;

/**
* Caching registry interceptor.
*
* @author <a href='mailto:Kevin.Conner@jboss.com'>Kevin Conner</a>
*/
public class CachingRegistryInterceptor extends AbstractRegistryInterceptor
{
    /**
     * The logger for the registry cache
     */
    private static final Logger LOGGER = Logger.getLogger(CachingRegistryInterceptor.class) ;
   
    /**
     * The default service cache size.
     */
    private static final int DEFAULT_MAX_CACHE_SIZE = 100 ;
    /**
     * The default cache validity period.
     */
    private static final long DEFAULT_VALIDITY_PERIOD = Environment.DEFAULT_REGISTRY_CACHE_LIFE_MILLIS_VALUE ;
   
    /**
     * The maximum number of services stored in the cache.
     */
    private static final int MAX_CACHE_SIZE ;
    /**
     * The validity period of the entry.
     */
    private static final long VALIDITY_PERIOD ;
   
    /**
     * The LRU map for the cached services.
     */
    private final LRUMap serviceInfoMap = new LRUMap(MAX_CACHE_SIZE) ;

    /**
     * Find all Services assigned to the Red Hat/JBossESB organization.
     * @return Collection of Strings containing the service names.
     * @throws RegistryException
     */
    public List<String> findAllServices() throws RegistryException
    {
        // Do not cache, go direct to the registry
        return getRegistry().findAllServices() ;
    }

    /**
     * Find all services that belong to the supplied category.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @return Collection of Strings containing the service names
     * @throws RegistryException
     */
    public List<String> findServices(final String category)
            throws RegistryException
    {
        // Do not cache, go direct to the registry
        return getRegistry().findServices(category) ;
    }

    /**
     * Returns the first EPR in the list that belong to a specific category and service combination.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @return EPR.
     * @throws RegistryException
     */
    public EPR findEPR(final String category, final String name)
            throws RegistryException, ServiceNotFoundException
    {
        final Service service = new Service(category, name) ;
        final ConcurrentMap<EPR, AtomicLong> eprs = getEPRs(service) ;
        final Iterator<EPR> eprIter = eprs.keySet().iterator() ;
        if (eprIter.hasNext())
        {
            return eprIter.next() ;
        }
        else
        {
            return null;
        }
    }

    /**
     * Finds all the EPRs that belong to a specific category and service combination.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @return Collection of EPRs.
     * @throws RegistryException
     */
    public List<EPR> findEPRs(final String category, final String name)
            throws RegistryException, ServiceNotFoundException
    {
        final Service service = new Service(category, name) ;
        final ConcurrentMap<EPR, AtomicLong> eprs = getEPRs(service) ;
        return Arrays.asList(eprs.keySet().toArray(new EPR[0])) ;
    }

    /**
     * Registers an EPR under the specified category and service. If the specified service does
     * not exist, it will be created at the same time.
     *
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @param serviceDescription  - human readable description of the service,
     *                             only used when it the service does not yet exist.
     * @param epr                 - the EndPointReference (EPR) that needs to be registered.
     * @param eprDescription      - human readable description of the EPR
     * @throws RegistryException
     */
    public void registerEPR(final String category, final String name,
            final String serviceDescription, final EPR epr, final String eprDescription)
            throws RegistryException
    {
        final Service service = new Service(category, name) ;
        final ServiceInfo serviceInfo = getServiceInfo(service) ;
        if (serviceInfo != null)
        {
            serviceInfo.acquireWriteLock() ;
        }
        try
        {
            getRegistry().registerEPR(category, name, serviceDescription, epr, eprDescription) ;
            if (serviceInfo != null)
            {
                final ConcurrentMap<EPR, AtomicLong> eprs = serviceInfo.getEPRs() ;
                if (eprs != null)
                {
                    addEPR(eprs, epr) ;
                }
            }
        }
        finally
        {
            if (serviceInfo != null)
            {
                serviceInfo.releaseWriteLock() ;
            }
        }
    }

    /**
     * Removes an EPR from the Registry.
     * @param serviceCategoryName - name of the category to which the service belongs.
     * @param serviceName         - name of the service to which the EPS belongs.
     * @param epr                 - the EndPointReference (EPR) that needs to be unregistered.
     * @throws RegistryException
     */
    public void unRegisterEPR(final String category, final String name,
            final EPR epr) throws RegistryException, ServiceNotFoundException
    {
        final Service service = new Service(category, name) ;
        final ServiceInfo serviceInfo = getServiceInfo(service) ;
        if (serviceInfo != null)
        {
            serviceInfo.acquireWriteLock() ;
        }
        try
        {
            getRegistry().unRegisterEPR(category, name, epr) ;
            if (serviceInfo != null)
            {
                final ConcurrentMap<EPR, AtomicLong> eprs = serviceInfo.getEPRs() ;
                if (eprs != null)
                {
                    final AtomicLong count = eprs.get(epr) ;
                    if (count != null)
                    {
                        if (count.decrementAndGet() == 0)
                        {
                            eprs.remove(epr) ;
                        }
                    }
                }
            }
        }
        finally
        {
            if (serviceInfo != null)
            {
                serviceInfo.releaseWriteLock() ;
            }
        }
    }

    /**
     * Removes a service from the Registry along with all the ServiceBindings underneath it.
     *
     * @param category           - name of the service category, for example 'transformation'.
     * @param serviceName        - name of the service, for example 'smooks'.
     * @throws RegistryException
     */
    public void unRegisterService(final String category, final String name)
            throws RegistryException, ServiceNotFoundException
    {
        final Service service = new Service(category, name) ;
        final ServiceInfo serviceInfo = getServiceInfo(service) ;
        if (serviceInfo != null)
        {
            serviceInfo.acquireWriteLock() ;
        }
        try
        {
            getRegistry().unRegisterService(category, name) ;
            removeServiceInfo(service) ;
            if (LOGGER.isDebugEnabled())
            {
                LOGGER.debug("Cache removing service " + service) ;
            }
        }
        finally
        {
            if (serviceInfo != null)
            {
                serviceInfo.releaseWriteLock() ;
            }
        }
    }

    /**
     * Get the service information if it is still valid.
     * @param service The service information.
     * @return The service information or null
     */
    private synchronized ServiceInfo getServiceInfo(final Service service)
    {
        final ServiceInfo serviceInfo = (ServiceInfo)serviceInfoMap.get(service) ;
        if (serviceInfo != null)
        {
            if (serviceInfo.isValid())
            {
                return serviceInfo ;
            }
            removeServiceInfo(service) ;
        }
        return null ;
    }

    /**
     * Create new service information or return current information if present.
     * @param service The service information.
     * @return The service information
     */
    private synchronized ServiceInfo createServiceInfo(final Service service)
    {
        final ServiceInfo serviceInfo = new ServiceInfo() ;
        final ServiceInfo origServiceInfo = (ServiceInfo)serviceInfoMap.put(service, serviceInfo) ;
        if ((origServiceInfo != null&& origServiceInfo.isValid())
        {
            serviceInfoMap.put(service, origServiceInfo) ;
            return origServiceInfo ;
        }
        else
        {
            return serviceInfo ;
        }
    }

    /**
     * Remove the service information from map.
     * @param service The service information
     */
    private synchronized void removeServiceInfo(final Service service)
    {
        serviceInfoMap.remove(service) ;
    }

    /**
     * Get the EPRs assocaited with the service, updating the cache if necessary
     * @param service The service to query.
     * @return The map of EPRs.
     * @throws RegistryException For errors accessing the registry delegate.
     * @throws ServiceNotFoundException If the service is not in the registry.
     */
    private ConcurrentMap<EPR, AtomicLong> getEPRs(final Service service)
        throws RegistryException, ServiceNotFoundException
    {
        final ServiceInfo serviceInfo = getServiceInfo(service) ;
        if (serviceInfo != null)
        {
            serviceInfo.acquireReadLock() ;
            try
            {
                final ConcurrentMap<EPR, AtomicLong> eprs = serviceInfo.getEPRs() ;
                if (eprs != null)
                {
                    return eprs ;
                }
            }
            finally
            {
                serviceInfo.releaseReadLock() ;
            }
        }
        final ServiceInfo newServiceInfo = createServiceInfo(service) ;
        newServiceInfo.acquireWriteLock() ;
        try
        {
            final ConcurrentMap<EPR, AtomicLong> eprs = newServiceInfo.getEPRs() ;
            if (eprs != null)
            {
                return eprs ;
            }
            else
            {
                final List<EPR> currentEPRs = getRegistry().findEPRs(service.getCategory(), service.getName()) ;
                final ConcurrentMap<EPR, AtomicLong> newEPRs = new ConcurrentHashMap<EPR, AtomicLong>() ;
                for(EPR epr: currentEPRs)
                {
                    addEPR(newEPRs, epr) ;
                }
                newServiceInfo.setEPRs(newEPRs) ;
                if (LOGGER.isDebugEnabled())
                {
                    LOGGER.debug("Cache reloaded for service " + service) ;
                }
                return newEPRs ;
            }
        }
        finally
        {
            newServiceInfo.releaseWriteLock() ;
        }
    }
   
    /**
     * Add an EPR entry into the map.
     * @param eprs The current map.
     * @param epr The epr to add.
     */
    private static void addEPR(final ConcurrentMap<EPR, AtomicLong> eprs, final EPR epr)
    {
        final AtomicLong newCount = new AtomicLong(1) ;
        final AtomicLong count = eprs.putIfAbsent(epr, newCount) ;
        if (count != null)
        {
            count.incrementAndGet() ;
        }
    }

    /**
     * Class representing the service information
     * @author kevin
     */
    private static class ServiceInfo
    {
        private final long expiryTime ;
       
        private ConcurrentMap<EPR, AtomicLong> eprs ;
       
        private ReadWriteLock lock = new ReentrantReadWriteLock() ;
       
        private ServiceInfo()
        {
            if (VALIDITY_PERIOD > 0)
            {
                expiryTime = System.currentTimeMillis() + VALIDITY_PERIOD ;
            }
            else
            {
                expiryTime = Long.MAX_VALUE ;
            }
        }
       
        boolean isValid()
        {
            return System.currentTimeMillis() < expiryTime ;
        }
       
        ConcurrentMap<EPR, AtomicLong> getEPRs()
        {
            return eprs ;
        }
       
        void setEPRs(final ConcurrentMap<EPR, AtomicLong> eprs)
        {
            this.eprs = eprs ;
        }
       
        void acquireWriteLock()
        {
            lock.writeLock().lock() ;
        }
       
        void releaseWriteLock()
        {
            lock.writeLock().unlock() ;
        }
       
        void acquireReadLock()
        {
            lock.readLock().lock() ;
        }
       
        void releaseReadLock()
        {
            lock.readLock().unlock() ;
        }
    }

    static
    {
        final String maxCacheSizeVal = Configuration.getRegistryCacheMaxSize() ;
        int maxCacheSize = DEFAULT_MAX_CACHE_SIZE ;
        if (maxCacheSizeVal != null)
        {
            try
            {
                maxCacheSize = Integer.parseInt(maxCacheSizeVal) ;
            }
            catch (final NumberFormatException nfe)
            {
                // fallback to default
                LOGGER.warn("Failed to parse maximum cache size, falling back to default", nfe) ;
            }
        }

        final String validityPeriodVal = Configuration.getRegistryCacheValidityPeriod() ;
        long validityPeriod = DEFAULT_VALIDITY_PERIOD ;
        if (validityPeriodVal != null)
        {
            try
            {
                validityPeriod = Long.parseLong(validityPeriodVal) ;
            }
            catch (final NumberFormatException nfe)
            {
                // fallback to default
                LOGGER.warn("Failed to parse validity period, falling back to default", nfe) ;
            }
        }
        VALIDITY_PERIOD = validityPeriod ;
        MAX_CACHE_SIZE = maxCacheSize ;
       
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("Registry cache validity period: " + VALIDITY_PERIOD) ;
            LOGGER.debug("Registry cache maximum size: " + MAX_CACHE_SIZE) ;
        }
    }
}
TOP

Related Classes of org.jboss.internal.soa.esb.services.registry.CachingRegistryInterceptor$ServiceInfo

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.