/* * Copyright © 2014 Cask Data, Inc. * * 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 co.cask.cdap.data2.transaction.queue.inmemory; import co.cask.cdap.common.queue.QueueName; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.Inject; import com.google.inject.Singleton; import java.io.PrintStream; import java.util.List; import java.util.concurrent.ConcurrentMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * Maintains all in-memory queues in the system. */ @Singleton public final class InMemoryQueueService { private final ConcurrentMap<QueueName, InMemoryQueue> queues; /** * Package visible constructor so that instance of this class can only be created through Guice. */ @Inject private InMemoryQueueService() { queues = Maps.newConcurrentMap(); } InMemoryQueue getQueue(QueueName queueName) { InMemoryQueue queue = queues.get(queueName); if (queue == null) { queue = new InMemoryQueue(); InMemoryQueue existing = queues.putIfAbsent(queueName, queue); if (existing != null) { queue = existing; } } return queue; } @SuppressWarnings("unused") public void dumpInfo(PrintStream out) { for (QueueName qname : queues.keySet()) { out.println("Queue '" + qname + "': size is " + queues.get(qname).getSize()); } } /** * Drop either all streams or all queues. * @param clearStreams if true, drops all streams, if false, clears all queues. * @param prefix if non-null, drops only queues with a name that begins with this prefix. */ private void resetAllQueuesOrStreams(boolean clearStreams, @Nullable String prefix) { List<QueueName> toRemove = Lists.newArrayListWithCapacity(queues.size()); for (QueueName queueName : queues.keySet()) { if ((clearStreams && queueName.isStream()) || (!clearStreams && queueName.isQueue())) { if (prefix == null || queueName.toString().startsWith(prefix)) { toRemove.add(queueName); } } } for (QueueName queueName : toRemove) { queues.remove(queueName); } } @SuppressWarnings("unused") public void resetQueues() { resetAllQueuesOrStreams(false, null); } public void resetQueuesWithPrefix(String prefix) { resetAllQueuesOrStreams(false, prefix); } @SuppressWarnings("unused") public void resetStreams() { resetAllQueuesOrStreams(true, null); } public void resetStreamsWithPrefix(String prefix) { resetAllQueuesOrStreams(true, prefix); } public boolean exists(QueueName queueName) { return queues.containsKey(queueName); } public void truncate(QueueName queueName) { InMemoryQueue queue = queues.get(queueName); if (queue != null) { queue.clear(); } } /** * Clear all streams or queues with a given prefix. * @param prefix the prefix to match. */ public void truncateAllWithPrefix(@Nonnull String prefix) { for (QueueName queueName : queues.keySet()) { if (queueName.toString().startsWith(prefix)) { truncate(queueName); } } } public void drop(QueueName queueName) { queues.remove(queueName); } }