/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.clustering.infinispan.subsystem; import static org.jboss.as.clustering.infinispan.InfinispanMessages.MESSAGES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import java.util.Iterator; import java.util.ListIterator; import java.util.Map; import org.infinispan.Cache; import org.infinispan.eviction.PassivationManager; import org.infinispan.factories.ComponentRegistry; import org.infinispan.interceptors.impl.CacheLoaderInterceptor; import org.infinispan.interceptors.impl.CacheMgmtInterceptor; import org.infinispan.interceptors.impl.CacheWriterInterceptor; import org.infinispan.interceptors.impl.InvalidationInterceptor; import org.infinispan.interceptors.impl.TxInterceptor; import org.infinispan.query.SearchManager; import org.infinispan.remoting.rpc.RpcManager; import org.infinispan.remoting.rpc.RpcManagerImpl; import org.infinispan.server.infinispan.SecurityActions; import org.infinispan.server.infinispan.spi.InfinispanSubsystem; import org.infinispan.server.infinispan.spi.service.CacheServiceName; import org.infinispan.topology.LocalTopologyManager; import org.infinispan.transaction.xa.recovery.RecoveryAdminOperations; import org.infinispan.upgrade.RollingUpgradeManager; import org.infinispan.xsite.XSiteAdminOperations; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.dmr.ModelNode; import org.jboss.msc.service.ServiceController; /** * Custom commands related to a cache * * @author Tristan Tarrant */ public abstract class CacheCommands implements OperationStepHandler { CacheCommands() { } /** * An attribute write handler which performs cache operations * * @param context the operation context * @param operation the operation being executed * @throws org.jboss.as.controller.OperationFailedException */ @Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); ListIterator<PathElement> iterator = address.iterator(); PathElement element = iterator.next(); while (!element.getValue().equals(InfinispanSubsystem.SUBSYSTEM_NAME)) { element = iterator.next(); } final String cacheContainerName = iterator.next().getValue(); final String cacheName = iterator.next().getValue(); if (context.isNormalServer()) { final ServiceController<?> controller = context.getServiceRegistry(false).getService(CacheServiceName.CACHE.getServiceName(cacheContainerName, cacheName)); Cache<?, ?> cache = (Cache<?, ?>) controller.getValue(); ModelNode operationResult = null; try { operationResult = invokeCommand(cache, operation, context); } catch (Exception e) { throw new OperationFailedException(MESSAGES.failedToInvokeOperation(e.getLocalizedMessage())); } if (operationResult != null) { context.getResult().set(operationResult); } } } protected abstract ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext operationContext) throws Exception; public static class ResetCacheStatisticsCommand extends CacheCommands { public static final ResetCacheStatisticsCommand INSTANCE = new ResetCacheStatisticsCommand(); public ResetCacheStatisticsCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.resetStatistics(cache.getAdvancedCache(), CacheMgmtInterceptor.class); return null; } } public static class ClearCacheCommand extends CacheCommands { public static final ClearCacheCommand INSTANCE = new ClearCacheCommand(); public ClearCacheCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.clearCache(cache.getAdvancedCache()); return null; } } public static class FlushCacheCommand extends CacheCommands { public static final FlushCacheCommand INSTANCE = new FlushCacheCommand(); public FlushCacheCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.flushCache(cache.getAdvancedCache()); return null; } } public static class StartCacheCommand extends CacheCommands { public static final StartCacheCommand INSTANCE = new StartCacheCommand(); public StartCacheCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.startCache(cache.getAdvancedCache()); return null; } } public static class StopCacheCommand extends CacheCommands { public static final StopCacheCommand INSTANCE = new StopCacheCommand(); public StopCacheCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.stopCache(cache.getAdvancedCache()); return null; } } public static class ShudownCacheCommand extends CacheCommands { public static final ShudownCacheCommand INSTANCE = new ShudownCacheCommand(); public ShudownCacheCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.shutdownCache(cache.getAdvancedCache()); return null; } } public static class ResetTxStatisticsCommand extends CacheCommands { public static final ResetTxStatisticsCommand INSTANCE = new ResetTxStatisticsCommand(); public ResetTxStatisticsCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.resetStatistics(cache.getAdvancedCache(), TxInterceptor.class); return null; } } public static class ResetInvalidationStatisticsCommand extends CacheCommands { public static final ResetInvalidationStatisticsCommand INSTANCE = new ResetInvalidationStatisticsCommand(); public ResetInvalidationStatisticsCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.resetStatistics(cache.getAdvancedCache(), InvalidationInterceptor.class); return null; } } public static class ResetActivationStatisticsCommand extends CacheCommands { public static final ResetActivationStatisticsCommand INSTANCE = new ResetActivationStatisticsCommand(); public ResetActivationStatisticsCommand() { } @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.resetStatistics(cache.getAdvancedCache(), CacheLoaderInterceptor.class); return null; } } public static class ResetPassivationStatisticsCommand extends CacheCommands { public static final ResetPassivationStatisticsCommand INSTANCE = new ResetPassivationStatisticsCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.resetStatistics(cache.getAdvancedCache(), PassivationManager.class); return null; } } public static class ResetRpcManagerStatisticsCommand extends CacheCommands { public static final ResetRpcManagerStatisticsCommand INSTANCE = new ResetRpcManagerStatisticsCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { RpcManagerImpl rpcManager = (RpcManagerImpl) SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(RpcManager.class); if (rpcManager != null) { rpcManager.resetStatistics(); } return null; } } public static class ResetCacheLoaderStatisticsCommand extends CacheCommands { public static final ResetCacheLoaderStatisticsCommand INSTANCE = new ResetCacheLoaderStatisticsCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SecurityActions.resetStatistics(cache.getAdvancedCache(), CacheWriterInterceptor.class); return null; } } public static class TransactionListInDoubtCommand extends CacheCommands { public static final TransactionListInDoubtCommand INSTANCE = new TransactionListInDoubtCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { RecoveryAdminOperations recoveryAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(RecoveryAdminOperations.class); return toOperationResult(recoveryAdminOperations.showInDoubtTransactions()); } } public static class TransactionForceCommitCommand extends CacheCommands { public static final TransactionForceCommitCommand INSTANCE = new TransactionForceCommitCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { long internalId = operation.require(ModelKeys.TX_INTERNAL_ID).asLong(); RecoveryAdminOperations recoveryAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(RecoveryAdminOperations.class); return toOperationResult(recoveryAdminOperations.forceCommit(internalId)); } } public static class TransactionForceRollbackCommand extends CacheCommands { public static final TransactionForceRollbackCommand INSTANCE = new TransactionForceRollbackCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { long internalId = operation.require(ModelKeys.TX_INTERNAL_ID).asLong(); RecoveryAdminOperations recoveryAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(RecoveryAdminOperations.class); return toOperationResult(recoveryAdminOperations.forceRollback(internalId)); } } public static class TransactionForgetCommand extends CacheCommands { public static final TransactionForgetCommand INSTANCE = new TransactionForgetCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { long internalId = operation.require(ModelKeys.TX_INTERNAL_ID).asLong(); RecoveryAdminOperations recoveryAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(RecoveryAdminOperations.class); return toOperationResult(recoveryAdminOperations.forget(internalId)); } } public static class BackupBringSiteOnlineCommand extends CacheCommands { public static final BackupBringSiteOnlineCommand INSTANCE = new BackupBringSiteOnlineCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); final String site = address.getLastElement().getValue(); XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.bringSiteOnline(site)); } } public static class BackupTakeSiteOfflineCommand extends CacheCommands { public static final BackupTakeSiteOfflineCommand INSTANCE = new BackupTakeSiteOfflineCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); final String site = address.getLastElement().getValue(); XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.takeSiteOffline(site)); } } public static class BackupSiteStatusCommand extends CacheCommands { public static final BackupSiteStatusCommand INSTANCE = new BackupSiteStatusCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); final String site = address.getLastElement().getValue(); XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.siteStatus(site)); } } public static class SynchronizeDataCommand extends CacheCommands { public static final SynchronizeDataCommand INSTANCE = new SynchronizeDataCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { ComponentRegistry registry = SecurityActions.getComponentRegistry(cache.getAdvancedCache()); RollingUpgradeManager manager = registry.getComponent(RollingUpgradeManager.class); if (manager != null) { int readBatch = CacheResource.READ_BATCH.resolveModelAttribute(context,operation).asInt(); int writeThreads = CacheResource.WRITE_THREADS.resolveModelAttribute(context,operation).asInt(); manager.synchronizeData(operation.require(ModelKeys.MIGRATOR_NAME).asString(), readBatch, writeThreads); } return null; } } public static class RecordGlobalKeySetCommand extends CacheCommands { public static final RecordGlobalKeySetCommand INSTANCE = new RecordGlobalKeySetCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { ComponentRegistry registry = SecurityActions.getComponentRegistry(cache.getAdvancedCache()); RollingUpgradeManager manager = registry.getComponent(RollingUpgradeManager.class); if (manager != null) { manager.recordKnownGlobalKeyset(); } return null; } } public static class DisconnectSourceCommand extends CacheCommands { public static final DisconnectSourceCommand INSTANCE = new DisconnectSourceCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { ComponentRegistry registry = SecurityActions.getComponentRegistry(cache.getAdvancedCache()); RollingUpgradeManager manager = registry.getComponent(RollingUpgradeManager.class); if (manager != null) { manager.disconnectSource(operation.require(ModelKeys.MIGRATOR_NAME).asString()); } return null; } } public static class BackupPushStateCommand extends CacheCommands { public static final BackupPushStateCommand INSTANCE = new BackupPushStateCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); final String site = address.getLastElement().getValue(); XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.pushState(site)); } } public static class BackupCancelPushStateCommand extends CacheCommands { public static final BackupCancelPushStateCommand INSTANCE = new BackupCancelPushStateCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); final String site = address.getLastElement().getValue(); XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.cancelPushState(site)); } } public static class BackupCancelReceiveStateCommand extends CacheCommands { public static final BackupCancelReceiveStateCommand INSTANCE = new BackupCancelReceiveStateCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { final PathAddress address = PathAddress.pathAddress(operation.require(OP_ADDR)); final String site = address.getLastElement().getValue(); XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.cancelReceiveState(site)); } } public static class BackupPushStateStatusCommand extends CacheCommands { public static final BackupPushStateStatusCommand INSTANCE = new BackupPushStateStatusCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(prettyPrintMap(xsiteAdminOperations.getPushStateStatus())); } } public static class BackupGetSendingSiteCommand extends CacheCommands { public static final BackupGetSendingSiteCommand INSTANCE = new BackupGetSendingSiteCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); return toOperationResult(xsiteAdminOperations.getSendingSiteName()); } } public static class BackupClearPushStatusCommand extends CacheCommands { public static final BackupClearPushStatusCommand INSTANCE = new BackupClearPushStatusCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { XSiteAdminOperations xsiteAdminOperations = SecurityActions.getComponentRegistry(cache.getAdvancedCache()).getComponent(XSiteAdminOperations.class); xsiteAdminOperations.clearPushStateStatus(); return null; } } public static class MassReindexCommand extends CacheCommands { public static final MassReindexCommand INSTANCE = new MassReindexCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext context) throws Exception { SearchManager searchManager = SecurityActions.getSearchManager(cache.getAdvancedCache()); if (searchManager != null) { searchManager.getMassIndexer().start(); } return null; } } public static class CacheRebalanceCommand extends CacheCommands { public static final CacheRebalanceCommand INSTANCE = new CacheRebalanceCommand(); @Override protected ModelNode invokeCommand(Cache<?, ?> cache, ModelNode operation, OperationContext operationContext) throws Exception { boolean value = SharedCacheResource.BOOL_VALUE.resolveModelAttribute(operationContext, operation).asBoolean(); LocalTopologyManager topologyManager = SecurityActions.getComponentRegistry(cache.getAdvancedCache()) .getComponent(LocalTopologyManager.class); if (topologyManager != null) { topologyManager.setCacheRebalancingEnabled(cache.getName(), value); } return null; } } private static ModelNode toOperationResult(String s) { ModelNode result = new ModelNode(); result.add(s); return result; } private static String prettyPrintMap(Map<?, ?> map) { if (map.isEmpty()) { return ""; } StringBuilder builder = new StringBuilder(); for (Iterator<? extends Map.Entry<?, ?>> iterator = map.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry<?, ?> entry = iterator.next(); builder.append(entry.getKey()).append("=").append(entry.getValue()); if (iterator.hasNext()) { builder.append(System.lineSeparator()); } } return builder.toString(); } }