static ExecutorService createDefaultExecutor() { final ThreadGroup group = new ThreadGroup("domain-mgmt-client-thread"); final ThreadFactory threadFactory = new JBossThreadFactory( group, Boolean.FALSE, null, "%G " + executorCount.incrementAndGet() + "-%t", null, null, doPrivileged(GetAccessControlContextAction.getInstance())); return new ThreadPoolExecutor( 4, 4, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(256), threadFactory); }
static final class HostControllerExecutorService implements Service<ExecutorService> { final ThreadFactory threadFactory = new JBossThreadFactory( new ThreadGroup("Host Controller Service Threads"), Boolean.FALSE, null, "%G - %t", null, null, doPrivileged(GetAccessControlContextAction.getInstance())); private ExecutorService executorService; @Override public synchronized void start(final StartContext context) throws StartException { executorService = new ThreadPoolExecutor( 0, Integer.MAX_VALUE, 5L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); } @Override public synchronized void stop(final StopContext context) { Thread executorShutdown = new Thread( new Runnable() { @Override public void run() { try { executorService.shutdown(); } finally { executorService = null; context.complete(); } } }, "HostController ExecutorService Shutdown Thread"); executorShutdown.start(); context.asynchronous(); } @Override public synchronized ExecutorService getValue() throws IllegalStateException { return executorService; } }
/** * Installs {@link MasterDomainControllerOperationHandlerImpl} which handles requests from slave DC * to master DC. * * @author <a href="*****@*****.**">Kabir Khan</a> */ public class MasterDomainControllerOperationHandlerService extends AbstractModelControllerOperationHandlerFactoryService { public static final ServiceName SERVICE_NAME = DomainController.SERVICE_NAME.append( ModelControllerClientOperationHandlerFactoryService.OPERATION_HANDLER_NAME_SUFFIX); private final DomainController domainController; private final HostControllerRegistrationHandler.OperationExecutor operationExecutor; private final TransactionalOperationExecutor txOperationExecutor; private final ManagementPongRequestHandler pongRequestHandler = new ManagementPongRequestHandler(); private final ThreadFactory threadFactory = new JBossThreadFactory( new ThreadGroup("slave-request-threads"), Boolean.FALSE, null, "%G - %t", null, null, doPrivileged(GetAccessControlContextAction.getInstance())); private final DomainControllerRuntimeIgnoreTransformationRegistry runtimeIgnoreTransformationRegistry; public MasterDomainControllerOperationHandlerService( final DomainController domainController, final HostControllerRegistrationHandler.OperationExecutor operationExecutor, TransactionalOperationExecutor txOperationExecutor, DomainControllerRuntimeIgnoreTransformationRegistry runtimeIgnoreTransformationRegistry) { this.domainController = domainController; this.operationExecutor = operationExecutor; this.txOperationExecutor = txOperationExecutor; this.runtimeIgnoreTransformationRegistry = runtimeIgnoreTransformationRegistry; } @Override public synchronized void start(StartContext context) throws StartException { pongRequestHandler.resetConnectionId(); super.start(context); } @Override public ManagementChannelHandler startReceiving(final Channel channel) { final ManagementChannelHandler handler = new ManagementChannelHandler( ManagementClientChannelStrategy.create(channel), getExecutor()); // Assemble the request handlers for the domain channel handler.addHandlerFactory( new HostControllerRegistrationHandler( handler, domainController, operationExecutor, getExecutor(), runtimeIgnoreTransformationRegistry)); handler.addHandlerFactory(new ModelControllerClientOperationHandler(getController(), handler)); handler.addHandlerFactory( new MasterDomainControllerOperationHandlerImpl(domainController, getExecutor())); handler.addHandlerFactory(pongRequestHandler); handler.addHandlerFactory( new DomainTransactionalProtocolOperationHandler(txOperationExecutor, handler)); channel.receiveMessage(handler.getReceiver()); return handler; } private class DomainTransactionalProtocolOperationHandler extends TransactionalProtocolOperationHandler { private final TransactionalOperationExecutor executor; private volatile SlaveRequest activeSlaveRequest; public DomainTransactionalProtocolOperationHandler( TransactionalOperationExecutor executor, ManagementChannelAssociation channelAssociation) { super(null, channelAssociation); this.executor = executor; } @Override protected ModelNode internalExecute( final ModelNode operation, final ManagementRequestContext<?> context, final OperationMessageHandler messageHandler, final ProxyOperationControl control, OperationAttachments attachments) { final OperationStepHandler handler; final String operationName = operation.require(OP).asString(); if (operationName.equals(PullDownDataForServerConfigOnSlaveHandler.OPERATION_NAME)) { handler = new PullDownDataForServerConfigOnSlaveHandler( SlaveChannelAttachments.getHostName(context.getChannel()), SlaveChannelAttachments.getTransformers(context.getChannel()), runtimeIgnoreTransformationRegistry); } else { throw HostControllerLogger.ROOT_LOGGER.cannotExecuteTransactionalOperationFromSlave( operationName); } Integer domainControllerLockId; if (operation .get(OPERATION_HEADERS) .hasDefined(DomainControllerLockIdUtils.DOMAIN_CONTROLLER_LOCK_ID)) { domainControllerLockId = operation .get(OPERATION_HEADERS, DomainControllerLockIdUtils.DOMAIN_CONTROLLER_LOCK_ID) .asInt(); } else { domainControllerLockId = null; } final Integer slaveLockId = operation .get(OPERATION_HEADERS, DomainControllerLockIdUtils.SLAVE_CONTROLLER_LOCK_ID) .asInt(); if (domainControllerLockId == null) { synchronized (this) { SlaveRequest slaveRequest = this.activeSlaveRequest; if (slaveRequest != null) { domainControllerLockId = slaveRequest.domainId; slaveRequest.refCount.incrementAndGet(); } } // TODO https://issues.jboss.org/browse/AS7-6809 If there are many slaves calling back many // of these threads will be blocked, and I // believe they are a finite resource } try { if (domainControllerLockId != null) { return executor.joinActiveOperation( operation, messageHandler, control, attachments, handler, domainControllerLockId); } else { ModelNode result = executor.executeAndAttemptLock( operation, messageHandler, control, attachments, new OperationStepHandler() { @Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { // Grab the lock id and store it Integer domainControllerLockId = CurrentOperationIdHolder.getCurrentOperationID(); synchronized (this) { activeSlaveRequest = new SlaveRequest(domainControllerLockId); } context.addStep(operation, handler, OperationContext.Stage.MODEL); context.stepCompleted(); } }); return result; } } finally { synchronized (this) { SlaveRequest slaveRequest = this.activeSlaveRequest; if (slaveRequest != null) { int refcount = slaveRequest.refCount.decrementAndGet(); if (refcount == 0) { activeSlaveRequest = null; } } } } } } public interface TransactionalOperationExecutor { ModelNode executeAndAttemptLock( ModelNode operation, OperationMessageHandler handler, ModelController.OperationTransactionControl control, OperationAttachments attachments, OperationStepHandler step); ModelNode joinActiveOperation( ModelNode operation, OperationMessageHandler handler, ModelController.OperationTransactionControl control, OperationAttachments attachments, OperationStepHandler step, int permit); } private final class SlaveRequest { private final int domainId; private final AtomicInteger refCount = new AtomicInteger(1); SlaveRequest(int domainId) { this.domainId = domainId; } } }