/* * Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * SPDX-License-Identifier: Apache-2.0 */ package com.amazonaws.dynamodb.bootstrap; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import com.amazonaws.dynamodb.bootstrap.DynamoDBEntryWithSize; /** * This class implements ILogConsumer, and when called to writeResult, it will * submit a new job to it's ExecutorCompletionService with a new * LogStashQueueWorker. It will then shutdown by adding a 'poison pill' to the * end of the blocking queue to notify that it has reached the end of the scan. */ public class BlockingQueueConsumer extends AbstractLogConsumer { private BlockingQueue<DynamoDBEntryWithSize> queue; public BlockingQueueConsumer(int numThreads) { this.queue = new ArrayBlockingQueue<DynamoDBEntryWithSize>(20); int numProcessors = Runtime.getRuntime().availableProcessors(); if (numProcessors > numThreads) { numThreads = numProcessors; } this.threadPool = Executors.newFixedThreadPool(numThreads); this.exec = new ExecutorCompletionService<Void>(threadPool); } @Override public Future<Void> writeResult(SegmentedScanResult result) { Future<Void> jobSubmission = null; try { jobSubmission = exec.submit(new BlockingQueueWorker(queue, result)); } catch (NullPointerException npe) { throw new NullPointerException( "Thread pool not initialized for LogStashExecutor"); } return jobSubmission; } /** * Returns the blocking queue to which the LogStashQueueWorkers add results */ public BlockingQueue<DynamoDBEntryWithSize> getQueue() { return queue; } /** * Shuts down the threadpool then adds a termination result to the end of * the queue. */ @Override public void shutdown(boolean awaitTermination) { super.shutdown(awaitTermination); boolean added = false; boolean interrupted = false; try { do { try { // a null entry with -1 size to notify the receiver that the // queue is done processing entries queue.put(new DynamoDBEntryWithSize(null, -1)); added = true; } catch (InterruptedException e) { interrupted = true; continue; } } while (!added); } finally { if (interrupted) { Thread.currentThread().interrupt(); } } } }