// // Copyright 2011 Cinch Logic Pty Ltd. // // http://www.chililog.com // // 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.chililog.server.pubsub; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; import org.chililog.server.common.ChiliLogException; import org.chililog.server.common.Log4JLogger; import org.chililog.server.engine.MqService; import org.hornetq.api.core.HornetQException; import org.hornetq.api.core.client.ClientProducer; import org.hornetq.api.core.client.ClientSession; /** * <p> * Pool of HornetQ producers used for publishing messages. This assumes that MqService has started. * </p> * <p> * Each producer has its own session. * </p> * <p> * All sessions use the "system user" credentials because it has access to all queues. Authentication is assumed to be * performed prior to using a session. * </p> * * <pre> * // Create pool * MqProducerSessionPool pool = new MqProducerSessionPool(); * * // Get a session from the pool * MqProducerSessionPool p = pool.getPooled(); * * try { * // Do some work * * // Returning a session to the pool * pool.returnPooled(p); * } catch (Exception ex) { * // In the event of an error, close the session and add a new item to the pool * try { * p.session.close(); * } catch (HornetQException e) { * } * pool.addPooled(); * throw ex; * } * * // Close connections * pool.cleanup(); * </pre> * * <p> * Pattern copied from <a href= * "http://source.jboss.org/browse/HornetQ/trunk/hornetq-rest/hornetq-rest/src/main/java/org/hornetq/rest/queue/PostMessage.java?r=10416&r=10416&r=10416" * >org.hornetq.rest.queue.PostMessage</a> * </p> * * @author vibul */ public class MqProducerSessionPool { static Log4JLogger _logger = Log4JLogger.getLogger(MqProducerSessionPool.class); protected ArrayBlockingQueue<Pooled> _pool = null; /** * <p> * Singleton constructor * </p> * <p> * If there is an exception, we log the error and exit because there's no point continuing without MQ client session * </p> * * @param poolSize * number of session to pool * @throws Exception */ public MqProducerSessionPool(int poolSize) { try { _pool = new ArrayBlockingQueue<Pooled>(poolSize); for (int i = 0; i < poolSize; i++) { addPooled(); } return; } catch (Exception e) { _logger.error("Error loading Publisher Session Pool: " + e.getMessage(), e); System.exit(1); } } /** * A pooled session and its associated producer */ public static class Pooled { public ClientSession session; public ClientProducer producer; private Pooled(ClientSession session, ClientProducer producer) { this.session = session; this.producer = producer; } } /** * Adds a new pooled item (session and its associated producer) to the pool * * @throws Exception */ public void addPooled() throws Exception { ClientSession session = MqService.getInstance().getNonTransactionalSystemClientSession(); ClientProducer producer = session.createProducer(); session.start(); _pool.add(new Pooled(session, producer)); } /** * Returns and removes a pooled session from the pool. * * @return a pooled item (session and its associated producer) * @throws InterruptedException * if interrupted while waiting for a session * @throws ChiliLogException * if no session are available after a 1 second wait */ public Pooled getPooled() throws Exception { Pooled pooled = _pool.poll(1, TimeUnit.SECONDS); if (pooled == null) { throw new ChiliLogException(Strings.GET_POOLED_PUBLISHER_SESSION_TIMEOUT_ERROR); } return pooled; } /** * Returns a pooled item that was retrieved using getPooled() to the pool. * * @param pooled * pooled item retrieved using getPooled() */ public void returnPooled(Pooled pooled) { _pool.add(pooled); } /** * Used during shutdown to close all sessions */ public void cleanup() { if (_pool == null) { return; } for (Pooled pooled : _pool) { try { pooled.session.close(); } catch (HornetQException e) { throw new RuntimeException(e); } } } /** * Returns the number of connections in the pool */ public int size() { return _pool.size(); } }