/* * 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.geode.management.internal.cli.commands; import org.apache.geode.SystemFailure; import org.apache.geode.cache.execute.ResultCollector; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.management.cli.CliMetaData; import org.apache.geode.management.cli.ConverterHint; import org.apache.geode.management.cli.Result; import org.apache.geode.management.cli.Result.Status; import org.apache.geode.management.internal.cli.CliUtil; import org.apache.geode.management.internal.cli.domain.AsyncEventQueueDetails; import org.apache.geode.management.internal.cli.functions.AsyncEventQueueFunctionArgs; import org.apache.geode.management.internal.cli.functions.CliFunctionResult; import org.apache.geode.management.internal.cli.functions.CreateAsyncEventQueueFunction; import org.apache.geode.management.internal.cli.functions.ListAsyncEventQueuesFunction; import org.apache.geode.management.internal.cli.i18n.CliStrings; import org.apache.geode.management.internal.cli.result.CommandResultException; import org.apache.geode.management.internal.cli.result.ResultBuilder; import org.apache.geode.management.internal.cli.result.TabularResultData; import org.apache.geode.management.internal.configuration.domain.XmlEntity; import org.apache.geode.management.internal.security.ResourceOperation; import org.apache.geode.security.ResourcePermission.Operation; import org.apache.geode.security.ResourcePermission.Resource; import org.springframework.shell.core.annotation.CliAvailabilityIndicator; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; /** * The QueueCommands class encapsulates all GemFire Queue commands in Gfsh. * </p> * * @since GemFire 8.0 */ public class QueueCommands extends AbstractCommandsSupport { @CliCommand(value = CliStrings.CREATE_ASYNC_EVENT_QUEUE, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__HELP) @ResourceOperation(resource = Resource.DATA, operation = Operation.MANAGE) public Result createAsyncEventQueue( @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__ID, mandatory = true, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__ID__HELP) String id, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__GROUP, unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE, optionContext = ConverterHint.MEMBERGROUP, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__GROUP__HELP) String[] groups, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__PARALLEL, unspecifiedDefaultValue = "false", specifiedDefaultValue = "true", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__PARALLEL__HELP) Boolean parallel, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__ENABLEBATCHCONFLATION, unspecifiedDefaultValue = "false", specifiedDefaultValue = "true", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__ENABLEBATCHCONFLATION__HELP) Boolean enableBatchConflation, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__BATCH_SIZE, unspecifiedDefaultValue = "100", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__BATCH_SIZE__HELP) int batchSize, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__BATCHTIMEINTERVAL, unspecifiedDefaultValue = "1000", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__BATCHTIMEINTERVAL__HELP) int batchTimeInterval, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__PERSISTENT, unspecifiedDefaultValue = "false", specifiedDefaultValue = "true", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__PERSISTENT__HELP) boolean persistent, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__DISK_STORE, unspecifiedDefaultValue = CliMetaData.ANNOTATION_NULL_VALUE, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__DISK_STORE__HELP) String diskStore, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__DISKSYNCHRONOUS, unspecifiedDefaultValue = "true", specifiedDefaultValue = "true", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__DISKSYNCHRONOUS__HELP) Boolean diskSynchronous, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__FORWARD_EXPIRATION_DESTROY, unspecifiedDefaultValue = "false", specifiedDefaultValue = "false", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__FORWARD_EXPIRATION_DESTROY__HELP) Boolean ignoreEvictionAndExpiration, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__MAXIMUM_QUEUE_MEMORY, unspecifiedDefaultValue = "100", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__MAXIMUM_QUEUE_MEMORY__HELP) int maxQueueMemory, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__DISPATCHERTHREADS, unspecifiedDefaultValue = "1", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__DISPATCHERTHREADS__HELP) Integer dispatcherThreads, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__ORDERPOLICY, unspecifiedDefaultValue = "KEY", help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__ORDERPOLICY__HELP) String orderPolicy, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__GATEWAYEVENTFILTER, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__GATEWAYEVENTFILTER__HELP) @CliMetaData( valueSeparator = ",") String[] gatewayEventFilters, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__SUBSTITUTION_FILTER, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__SUBSTITUTION_FILTER__HELP) String gatewaySubstitutionListener, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__LISTENER, mandatory = true, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__LISTENER__HELP) String listener, @CliOption(key = CliStrings.CREATE_ASYNC_EVENT_QUEUE__LISTENER_PARAM_AND_VALUE, help = CliStrings.CREATE_ASYNC_EVENT_QUEUE__LISTENER_PARAM_AND_VALUE__HELP, optionContext = ConverterHint.STRING_DISABLER) @CliMetaData( valueSeparator = ",") String[] listenerParamsAndValues) { Properties listenerProperties = new Properties(); try { if (listenerParamsAndValues != null) { for (int i = 0; i < listenerParamsAndValues.length; i++) { final int hashPosition = listenerParamsAndValues[i].indexOf('#'); if (hashPosition == -1) { listenerProperties.put(listenerParamsAndValues[i], ""); } else { listenerProperties.put(listenerParamsAndValues[i].substring(0, hashPosition), listenerParamsAndValues[i].substring(hashPosition + 1)); } } } TabularResultData tabularData = ResultBuilder.createTabularResultData(); boolean accumulatedData = false; Set<DistributedMember> targetMembers; try { targetMembers = CliUtil.findMembersOrThrow(groups, null); } catch (CommandResultException crex) { return crex.getResult(); } AsyncEventQueueFunctionArgs aeqArgs = new AsyncEventQueueFunctionArgs(id, parallel, enableBatchConflation, batchSize, batchTimeInterval, persistent, diskStore, diskSynchronous, maxQueueMemory, dispatcherThreads, orderPolicy, gatewayEventFilters, gatewaySubstitutionListener, listener, listenerProperties, ignoreEvictionAndExpiration); ResultCollector<?, ?> rc = CliUtil.executeFunction(new CreateAsyncEventQueueFunction(), aeqArgs, targetMembers); List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult()); AtomicReference<XmlEntity> xmlEntity = new AtomicReference<>(); for (CliFunctionResult result : results) { if (result.getThrowable() != null) { tabularData.accumulate("Member", result.getMemberIdOrName()); tabularData.accumulate("Result", "ERROR: " + result.getThrowable().getClass().getName() + ": " + result.getThrowable().getMessage()); accumulatedData = true; tabularData.setStatus(Status.ERROR); } else if (result.isSuccessful()) { tabularData.accumulate("Member", result.getMemberIdOrName()); tabularData.accumulate("Result", result.getMessage()); accumulatedData = true; if (xmlEntity.get() == null) { xmlEntity.set(result.getXmlEntity()); } } } if (!accumulatedData) { return ResultBuilder.createInfoResult("Unable to create async event queue(s)."); } Result result = ResultBuilder.buildResult(tabularData); if (xmlEntity.get() != null) { persistClusterConfiguration(result, () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), groups)); } return result; } catch (VirtualMachineError e) { SystemFailure.initiateFailure(e); throw e; } catch (Throwable th) { SystemFailure.checkFailure(); return ResultBuilder.createGemFireErrorResult( CliStrings.format(CliStrings.CREATE_ASYNC_EVENT_QUEUE__ERROR_WHILE_CREATING_REASON_0, new Object[] {th.getMessage()})); } } @CliCommand(value = CliStrings.LIST_ASYNC_EVENT_QUEUES, help = CliStrings.LIST_ASYNC_EVENT_QUEUES__HELP) @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) public Result listAsyncEventQueues() { try { TabularResultData tabularData = ResultBuilder.createTabularResultData(); boolean accumulatedData = false; Set<DistributedMember> targetMembers; try { targetMembers = CliUtil.findMembersOrThrow((String) null, (String) null); } catch (CommandResultException crex) { return crex.getResult(); } ResultCollector<?, ?> rc = CliUtil.executeFunction(new ListAsyncEventQueuesFunction(), new Object[] {}, targetMembers); List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult()); for (CliFunctionResult result : results) { if (result.getThrowable() != null) { tabularData.accumulate("Member", result.getMemberIdOrName()); tabularData.accumulate("Result", "ERROR: " + result.getThrowable().getClass().getName() + ": " + result.getThrowable().getMessage()); accumulatedData = true; tabularData.setStatus(Status.ERROR); } else { AsyncEventQueueDetails[] details = (AsyncEventQueueDetails[]) result.getSerializables(); for (int i = 0; i < details.length; i++) { tabularData.accumulate("Member", result.getMemberIdOrName()); tabularData.accumulate("ID", details[i].getId()); tabularData.accumulate("Batch Size", details[i].getBatchSize()); tabularData.accumulate("Persistent", details[i].isPersistent()); tabularData.accumulate("Disk Store", details[i].getDiskStoreName()); tabularData.accumulate("Max Memory", details[i].getMaxQueueMemory()); Properties listenerProperties = details[i].getListenerProperties(); if (listenerProperties == null || listenerProperties.size() == 0) { tabularData.accumulate("Listener", details[i].getListener()); } else { StringBuilder propsStringBuilder = new StringBuilder(); propsStringBuilder.append('('); boolean firstProperty = true; for (Map.Entry<Object, Object> property : listenerProperties.entrySet()) { if (!firstProperty) { propsStringBuilder.append(','); } else { firstProperty = false; } propsStringBuilder.append(property.getKey()).append('=') .append(property.getValue()); } propsStringBuilder.append(')'); tabularData.accumulate("Listener", details[i].getListener() + propsStringBuilder.toString()); } accumulatedData = true; } } } if (!accumulatedData) { return ResultBuilder .createInfoResult(CliStrings.LIST_ASYNC_EVENT_QUEUES__NO_QUEUES_FOUND_MESSAGE); } return ResultBuilder.buildResult(tabularData); } catch (VirtualMachineError e) { SystemFailure.initiateFailure(e); throw e; } catch (Throwable th) { SystemFailure.checkFailure(); return ResultBuilder.createGemFireErrorResult( CliStrings.format(CliStrings.LIST_ASYNC_EVENT_QUEUES__ERROR_WHILE_LISTING_REASON_0, new Object[] {th.getMessage()})); } } @CliAvailabilityIndicator({CliStrings.CREATE_ASYNC_EVENT_QUEUE, CliStrings.LIST_ASYNC_EVENT_QUEUES}) public boolean queueCommandsAvailable() { boolean isAvailable = true; if (CliUtil.isGfshVM()) { isAvailable = getGfsh() != null && getGfsh().isConnectedAndReady(); } return isAvailable; } }