/* * -----------------------------------------------------------------------\ * * PerfCake * * *   * Copyright (C) 2010 - 2016 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.perfcake.message.sender; import org.perfcake.PerfCakeException; import org.perfcake.util.ObjectFactory; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * Manages concurrent friendly pool of senders. * * @author <a href="mailto:pavel.macik@gmail.com">Pavel Macík</a> * @author <a href="mailto:marvenec@gmail.com">Martin Večeřa</a> */ public class MessageSenderManager { /** * Number of available senders ready to send the message. Internally configured to reflect number of threads configured in a generator. */ private int senderPoolSize = 100; /** * Name of the class implementing the sender used in the scenario execution. */ private String senderClass; /** * Properties of message sender that will be passed to sender instances. */ private final Properties messageSenderProperties = new Properties(); /** * Senders available to send messages. */ private final Queue<MessageSender> availableSenders = new ConcurrentLinkedQueue<>(); /** * All the senders created including those actually busy. */ private final List<MessageSender> allSenders = new ArrayList<>(); /** * Sets a message sender property. * * @param property * Property name to be set. * @param value * A new property string value. */ public void setMessageSenderProperty(final String property, final String value) { messageSenderProperties.put(property, value); } /** * Sets a message sender property. * * @param property * Object referencing the property to be set. * @param value * A new property value. */ public void setMessageSenderProperty(final Object property, final Object value) { messageSenderProperties.put(property, value); } /** * Copies properties to message sender properties. * * @param properties * Properties to be added. */ public void addMessageSenderProperties(final Properties properties) { if (properties != null) { messageSenderProperties.putAll(properties); } } /** * Initializes the message sender by creating all the message sender instances. * * @throws PerfCakeException * When it was not possible to create the instances. */ public void init() throws PerfCakeException { availableSenders.clear(); for (int i = 0; i < senderPoolSize; i++) { try { final MessageSender sender = (MessageSender) ObjectFactory.summonInstance(senderClass, messageSenderProperties); addSenderInstance(sender); } catch (Exception e) { throw new PerfCakeException("Unable to instantiate sender class: ", e); } } } /** * Adds {@link MessageSender} into available senders and initializes it. * * @param sender * Sender to be registered with this manager. * @throws PerfCakeException * When the initialization of the sender fails. */ public void addSenderInstance(final MessageSender sender) throws PerfCakeException { sender.init(); availableSenders.add(sender); allSenders.add(sender); } /** * Gets a free sender from the pool. * * @return A sender that is ready to send a message. * @throws org.perfcake.PerfCakeException * When the pool is empty. */ public MessageSender acquireSender() throws PerfCakeException { final MessageSender ms = availableSenders.poll(); if (ms != null) { return ms; } else { throw new PerfCakeException("MessageSender pool is empty."); } } /** * Returns a sender that has been already used to the pool of available senders for later reuse. * * @param messageSender * The sender to be returned to the pool. */ public void releaseSender(final MessageSender messageSender) { availableSenders.offer(messageSender); } /** * Release all senders that has been acquired previously. */ public void releaseAllSenders() { for (final MessageSender ms : allSenders) { if (!availableSenders.contains(ms)) { availableSenders.offer(ms); } } } /** * Gets the number of available senders in the pool. * * @return The number of available senders in the pool. */ public int availableSenderCount() { return availableSenders.size(); } /** * Finalizes the message sender manager and disconnects all message senders from their target. * * @throws PerfCakeException * When the disconnection operation failed. */ public void close() throws PerfCakeException { for (final MessageSender ms : allSenders) { ms.close(); } } /** * Gets the size of the pool of senders. * * @return The size of the pool of senders. */ public int getSenderPoolSize() { return senderPoolSize; } /** * Sets the size of the pool of senders. * * @param senderPoolSize * The size of the pool of senders. */ public void setSenderPoolSize(final int senderPoolSize) { this.senderPoolSize = senderPoolSize; } /** * Gets the name of the class implementing the message sender. * * @return The name of the class implementing the message sender. */ public String getSenderClass() { return senderClass; } /** * Sets the name of the class implementing the message sender. * * @param senderClass * The name of the class implementing the message sender. */ public void setSenderClass(final String senderClass) { this.senderClass = senderClass; } }