| 30 | import org.slf4j.LoggerFactory; |
| 31 | |
| 32 | @SuppressWarnings("checkstyle:AbbreviationAsWordInName") |
| 33 | public class JCQueue implements Closeable { |
| 34 | private static final Logger LOG = LoggerFactory.getLogger(JCQueue.class); |
| 35 | private final ExitCondition continueRunning = () -> true; |
| 36 | private final List<JCQueueMetrics> jcqMetrics = new ArrayList<>(); |
| 37 | private final MpscArrayQueue<Object> recvQueue; |
| 38 | // only holds msgs from other workers (via WorkerTransfer), when recvQueue is full |
| 39 | private final MpscUnboundedArrayQueue<Object> overflowQ; |
| 40 | private final int overflowLimit; // ensures... overflowCount <= overflowLimit. if set to 0, disables overflow limiting. |
| 41 | private final int producerBatchSz; |
| 42 | private final DirectInserter directInserter = new DirectInserter(this); |
| 43 | private final ThreadLocal<BatchInserter> thdLocalBatcher = new ThreadLocal<BatchInserter>(); // ensure 1 instance per producer thd. |
| 44 | private final IWaitStrategy backPressureWaitStrategy; |
| 45 | private final String queueName; |
| 46 | |
| 47 | public JCQueue(String queueName, String metricNamePrefix, int size, int overflowLimit, int producerBatchSz, |
| 48 | IWaitStrategy backPressureWaitStrategy, String topologyId, String componentId, List<Integer> taskIds, |
| 49 | int port, StormMetricRegistry metricRegistry) { |
| 50 | this.queueName = queueName; |
| 51 | this.overflowLimit = overflowLimit; |
| 52 | this.recvQueue = new MpscArrayQueue<>(size); |
| 53 | this.overflowQ = new MpscUnboundedArrayQueue<>(size); |
| 54 | |
| 55 | for (Integer taskId : taskIds) { |
| 56 | this.jcqMetrics.add(new JCQueueMetrics(metricNamePrefix, topologyId, componentId, taskId, port, |
| 57 | metricRegistry, recvQueue, overflowQ)); |
| 58 | } |
| 59 | |
| 60 | //The batch size can be no larger than half the full recvQueue size, to avoid contention issues. |
| 61 | this.producerBatchSz = Math.max(1, Math.min(producerBatchSz, size / 2)); |
| 62 | this.backPressureWaitStrategy = backPressureWaitStrategy; |
| 63 | } |
| 64 | |
| 65 | public String getQueueName() { |
| 66 | return queueName; |
| 67 | } |
| 68 | |
| 69 | @Override |
| 70 | public void close() { |
| 71 | for (JCQueueMetrics jcQueueMetric : jcqMetrics) { |
| 72 | jcQueueMetric.close(); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /** |
| 77 | * Non blocking. Returns immediately if Q is empty. Returns number of elements consumed from Q. |
| 78 | */ |
| 79 | public int consume(JCQueue.Consumer consumer) { |
| 80 | return consume(consumer, continueRunning); |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Non blocking. Returns immediately if Q is empty. Runs till Q is empty OR exitCond.keepRunning() return false. Returns number of |
| 85 | * elements consumed from Q. |
| 86 | */ |
| 87 | public int consume(JCQueue.Consumer consumer, ExitCondition exitCond) { |
| 88 | try { |
| 89 | return consumeImpl(consumer, exitCond); |