/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.cassandra.concurrent;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.cassandra.config.DatabaseDescriptor;
import static org.apache.cassandra.config.DatabaseDescriptor.getConcurrentReaders;
import static org.apache.cassandra.config.DatabaseDescriptor.getConcurrentWriters;
/**
* This class manages executor services for Messages recieved: each Message requests
* running on a specific "stage" for concurrency control; hence the Map approach,
* even though stages (executors) are not created dynamically.
*/
public class StageManager
{
private static Map<String, ThreadPoolExecutor> stages = new HashMap<String, ThreadPoolExecutor>();
public final static String READ_STAGE = "ROW-READ-STAGE";
public final static String MUTATION_STAGE = "ROW-MUTATION-STAGE";
public final static String STREAM_STAGE = "STREAM-STAGE";
public final static String GOSSIP_STAGE = "GS";
public static final String RESPONSE_STAGE = "RESPONSE-STAGE";
public final static String AE_SERVICE_STAGE = "AE-SERVICE-STAGE";
private static final String LOADBALANCE_STAGE = "LOAD-BALANCER-STAGE";
public static final String SNAPSHOT_ARCHIVE_STAGE = "SNAPSHOT-ARCHIVE-STAGE";
static
{
stages.put(MUTATION_STAGE, multiThreadedConfigurableStage(MUTATION_STAGE, getConcurrentWriters()));
stages.put(READ_STAGE, multiThreadedConfigurableStage(READ_STAGE, getConcurrentReaders()));
stages.put(RESPONSE_STAGE, multiThreadedStage("RESPONSE-STAGE", Math.max(2, Runtime.getRuntime().availableProcessors())));
// the rest are all single-threaded
stages.put(STREAM_STAGE, new JMXEnabledThreadPoolExecutor(STREAM_STAGE));
stages.put(GOSSIP_STAGE, new JMXEnabledThreadPoolExecutor("GMFD"));
stages.put(AE_SERVICE_STAGE, new JMXEnabledThreadPoolExecutor(AE_SERVICE_STAGE));
stages.put(LOADBALANCE_STAGE, new JMXEnabledThreadPoolExecutor(LOADBALANCE_STAGE));
if (DatabaseDescriptor.isDataArchiveEnabled())
{
stages.put(SNAPSHOT_ARCHIVE_STAGE, new JMXEnabledThreadPoolExecutor(SNAPSHOT_ARCHIVE_STAGE));
}
}
private static ThreadPoolExecutor multiThreadedStage(String name, int numThreads)
{
// avoid running afoul of requirement in DebuggableThreadPoolExecutor that single-threaded executors
// must have unbounded queues
assert numThreads > 1 : "multi-threaded stages must have at least 2 threads";
return new JMXEnabledThreadPoolExecutor(numThreads,
numThreads,
Integer.MAX_VALUE,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
new NamedThreadFactory(name));
}
private static ThreadPoolExecutor multiThreadedConfigurableStage(String name, int numThreads)
{
assert numThreads > 1 : "multi-threaded stages must have at least 2 threads";
return new StageThreadPoolExecutor(numThreads,
numThreads,
Integer.MAX_VALUE,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
name);
}
/**
* Retrieve a stage from the StageManager
* @param stageName name of the stage to be retrieved.
*/
public static ThreadPoolExecutor getStage(String stageName)
{
return stages.get(stageName);
}
/**
* This method shuts down all registered stages.
*/
public static void shutdownNow()
{
Set<String> stages = StageManager.stages.keySet();
for (String stage : stages)
{
StageManager.stages.get(stage).shutdownNow();
}
}
}