/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU LESSER GENERAL PUBLIC * LICENSE as published by the Free Software Foundation under * version 3 of the License * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * LESSER GENERAL PUBLIC LICENSE v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.api.pools; import java.util.HashMap; import java.util.Map; import org.apache.commons.pool.impl.GenericObjectPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.abiquo.api.exceptions.APIError; import com.abiquo.api.pools.impl.VSMClientPool; import com.abiquo.api.services.DefaultApiService; import com.abiquo.server.core.infrastructure.RemoteService; /** * Global remote service client pool. * <p> * This class provides generic access to remote service clients and allows to configure the * connection pools for each one. * * @author Ignasi Barrera * @param <T> The type of the remote service client. */ @Service public class RemoteServiceClientPool extends DefaultApiService { /** The logger. */ private final static Logger LOGGER = LoggerFactory.getLogger(RemoteServiceClientPool.class); /** * A map of remote service client pools holding single connection pools for each remote service * in each datacenter. */ private Map<String, Pool< ? >> pools = new HashMap<String, Pool< ? >>(); /** * Get a remote service client from the pool to connect to the given remote service. * * @param remoteService The target remote service. * @return The remote service client used to connect to the remote service. */ public Object getClientFor(final RemoteService remoteService) { Pool< ? > pool = getPoolForRemoteService(remoteService); Object client = null; try { client = pool.borrowObject(); } catch (Exception ex) { LOGGER.error(APIError.REMOTE_SERVICE_ERROR_BORROWING.getMessage(), ex); addUnexpectedErrors(APIError.REMOTE_SERVICE_ERROR_BORROWING); flushErrors(); } return client; } /** * Returns a remote service client to the pool. * * @param remoteService The target remote service. * @param client The remote service client to return to the pool. */ public void releaseClientFor(final RemoteService remoteService, final Object client) { Pool< ? > pool = getPoolForRemoteService(remoteService); try { pool.returnObject(client); } catch (Exception ex) { LOGGER.trace("Unable to return remote service client for " + remoteService.getUri() + " to the pool", ex); } } /** * Get the remote service client pool for the given remote service. * <p> * This method will create a new pool if none exists. * * @param remoteService The remote service to get the client pool for. * @return The remote service client pool for the given remote service. */ protected Pool< ? > getPoolForRemoteService(final RemoteService remoteService) { Pool< ? > pool = pools.get(remoteService.getUri()); if (pool == null) { pool = createClientPoolFor(remoteService); } return pool; } /** * Create a new remote service client pool for the given remote service. * * @param remoteService The remote service to create the client pool for. * @return The remote service client pool for the given remote service. */ protected Pool< ? > createClientPoolFor(final RemoteService remoteService) { Pool< ? > pool = null; switch (remoteService.getType()) { case VIRTUAL_SYSTEM_MONITOR: pool = new VSMClientPool(remoteService); break; default: LOGGER.error(APIError.REMOTE_SERVICE_NON_POOLABLE.getMessage()); addUnexpectedErrors(APIError.REMOTE_SERVICE_NON_POOLABLE); flushErrors(); break; } return pool; } /** * The pool object itself. * <p> * This class will be the responsible for managing the objects in the pool. * * @author Ignasi Barrera * @param <T> The type of the objects to be added to the pool. */ public static class Pool<T> extends GenericObjectPool { /** * Creates the pool for clients connecting to the given remote service. * * @param remoteService The target remote service. */ public Pool(final PoolableRemoteServiceClientFactory factory) { super(factory); } } }