/** * Copyright 2015 Otto (GmbH & Co KG) * * 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 com.ottogroup.bi.spqr.pipeline.queue.memory; import java.util.Properties; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.codahale.metrics.Counter; import com.ottogroup.bi.spqr.exception.RequiredInputMissingException; import com.ottogroup.bi.spqr.pipeline.message.StreamingDataMessage; import com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue; import com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueueConsumer; import com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueueProducer; import com.ottogroup.bi.spqr.pipeline.queue.chronicle.DefaultStreamingMessageQueue; import com.ottogroup.bi.spqr.pipeline.queue.strategy.StreamingMessageQueueBlockingWaitStrategy; import com.ottogroup.bi.spqr.pipeline.queue.strategy.StreamingMessageQueueDirectPassStrategy; import com.ottogroup.bi.spqr.pipeline.queue.strategy.StreamingMessageQueueSleepingWaitStrategy; import com.ottogroup.bi.spqr.pipeline.queue.strategy.StreamingMessageQueueWaitStrategy; /** * Memory based implementation of {@link StreamingDataMessage}. Compared to {@link DefaultStreamingMessageQueue} * this is fully based on in-memory structures and thus does not provide any message persistence features. * @author mnxfst * @since Jul 3, 2015 */ public class InMemoryStreamingMessageQueue implements StreamingMessageQueue { /** our faithful logging facility ..... ;-) */ private static final Logger logger = Logger.getLogger(InMemoryStreamingMessageQueue.class); ///////////////////////////////////////////////////////////////////// // available configuration options public static final String CFG_QUEUE_MESSAGE_WAIT_STRATEGY = "queue.message.waitStrategy"; ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // setting for 'type' property to get an instance of this type public static final String CFG_QUEUE_TYPE = "memory"; ///////////////////////////////////////////////////////////////////// /** unique queue identifier */ private String id = null; /** internal queue holding elements */ private ConcurrentLinkedQueue<StreamingDataMessage> queue = new ConcurrentLinkedQueue<StreamingDataMessage>(); /** message queue consumer */ private InMemoryStreamingMessageQueueConsumer queueConsumer = null; /** message queue producer */ private InMemoryStreamingMessageQueueProducer queueProducer = null; /** wait strategy */ private StreamingMessageQueueWaitStrategy queueWaitStrategy = null; /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#initialize(java.util.Properties) */ public void initialize(Properties properties) throws RequiredInputMissingException { //////////////////////////////////////////////////////////////////////////////// // extract and validate input if(properties == null) throw new RequiredInputMissingException("Missing required properties"); if(StringUtils.isBlank(this.id)) throw new RequiredInputMissingException("Missing required queue identifier"); this.queueWaitStrategy = getWaitStrategy(StringUtils.trim(properties.getProperty(CFG_QUEUE_MESSAGE_WAIT_STRATEGY))); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // initialize producer and consumer instances this.queueProducer = new InMemoryStreamingMessageQueueProducer(this.id, this.queue, this.queueWaitStrategy); this.queueConsumer = new InMemoryStreamingMessageQueueConsumer(this.id, this.queue, this.queueWaitStrategy); //////////////////////////////////////////////////////////////////////////////// logger.info("In-memory streaming message queue successfully initialized"); } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#shutdown() */ public boolean shutdown() { this.queue.clear(); return true; } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#insert(com.ottogroup.bi.spqr.pipeline.message.StreamingDataMessage) */ public boolean insert(StreamingDataMessage message) { if(message != null) return this.queue.offer(message); return false; } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#next() */ public StreamingDataMessage next() { return this.queue.poll(); } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#getProducer() */ public StreamingMessageQueueProducer getProducer() { return this.queueProducer; } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#getConsumer() */ public StreamingMessageQueueConsumer getConsumer() { return this.queueConsumer; } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#setMessageInsertionCounter(com.codahale.metrics.Counter) */ public void setMessageInsertionCounter(Counter counter) { this.queueProducer.setMessageInsertionCounter(counter); } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#setMessageRetrievalCounter(com.codahale.metrics.Counter) */ public void setMessageRetrievalCounter(Counter counter) { this.queueConsumer.setMessageRetrievalCounter(counter); } /** * Return an instance of the referenced {@link StreamingMessageQueueWaitStrategy} * @param waitStrategyName name of strategy to instantiate (eg. {@link StreamingMessageQueueBlockingWaitStrategy#STRATEGY_NAME} (default)) * @return */ protected StreamingMessageQueueWaitStrategy getWaitStrategy(final String waitStrategyName) { if(StringUtils.equalsIgnoreCase(waitStrategyName, StreamingMessageQueueDirectPassStrategy.STRATEGY_NAME)) return new StreamingMessageQueueDirectPassStrategy(); else if(StringUtils.equalsIgnoreCase(waitStrategyName, StreamingMessageQueueSleepingWaitStrategy.STRATEGY_NAME)) return new StreamingMessageQueueSleepingWaitStrategy(); return new StreamingMessageQueueBlockingWaitStrategy(); } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#setId(java.lang.String) */ public void setId(String id) { this.id = id; } /** * @see com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue#getId() */ public String getId() { return this.id; } public long getSize() { return this.queue.size(); } }