http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommands.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommands.java new file mode 100644 index 0000000..c5d859e --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommands.java @@ -0,0 +1,420 @@ +/* + * 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 java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.springframework.shell.core.annotation.CliCommand; +import org.springframework.shell.core.annotation.CliOption; + +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.internal.cli.CliUtil; +import org.apache.geode.management.internal.cli.domain.DurableCqNamesResult; +import org.apache.geode.management.internal.cli.domain.MemberResult; +import org.apache.geode.management.internal.cli.domain.SubscriptionQueueSizeResult; +import org.apache.geode.management.internal.cli.functions.CloseDurableClientFunction; +import org.apache.geode.management.internal.cli.functions.CloseDurableCqFunction; +import org.apache.geode.management.internal.cli.functions.GetSubscriptionQueueSizeFunction; +import org.apache.geode.management.internal.cli.functions.ListDurableCqNamesFunction; +import org.apache.geode.management.internal.cli.i18n.CliStrings; +import org.apache.geode.management.internal.cli.result.ErrorResultData; +import org.apache.geode.management.internal.cli.result.InfoResultData; +import org.apache.geode.management.internal.cli.result.ResultBuilder; +import org.apache.geode.management.internal.cli.result.TabularResultData; +import org.apache.geode.management.internal.security.ResourceOperation; +import org.apache.geode.security.ResourcePermission.Operation; +import org.apache.geode.security.ResourcePermission.Resource; +import org.apache.geode.security.ResourcePermission.Target; + +/** + * The DurableClientCommands class encapsulates all GemFire shell (Gfsh) commands related to durable + * clients and cqs defined in GemFire. + * </p> + */ +@SuppressWarnings("unused") +public class DurableClientCommands implements GfshCommand { + + private static final ListDurableCqNamesFunction listDurableCqNamesFunction = + new ListDurableCqNamesFunction(); + private static final CloseDurableClientFunction closeDurableClientFunction = + new CloseDurableClientFunction(); + private static final CloseDurableCqFunction closeDurableCqFunction = new CloseDurableCqFunction(); + private static final GetSubscriptionQueueSizeFunction countDurableCqEvents = + new GetSubscriptionQueueSizeFunction(); + + @CliCommand(value = CliStrings.LIST_DURABLE_CQS, help = CliStrings.LIST_DURABLE_CQS__HELP) + @CliMetaData() + @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) + public Result listDurableClientCqs( + @CliOption(key = CliStrings.LIST_DURABLE_CQS__DURABLECLIENTID, mandatory = true, + help = CliStrings.LIST_DURABLE_CQS__DURABLECLIENTID__HELP) final String durableClientId, + + @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, + help = CliStrings.LIST_DURABLE_CQS__MEMBER__HELP, + optionContext = ConverterHint.MEMBERIDNAME) final String[] memberNameOrId, + + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + help = CliStrings.LIST_DURABLE_CQS__GROUP__HELP, + optionContext = ConverterHint.MEMBERGROUP) final String[] group) { + Result result; + try { + + boolean noResults = true; + Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId); + + if (targetMembers.isEmpty()) { + return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); + } + + final ResultCollector<?, ?> rc = + CliUtil.executeFunction(new ListDurableCqNamesFunction(), durableClientId, targetMembers); + final List<DurableCqNamesResult> results = (List<DurableCqNamesResult>) rc.getResult(); + Map<String, List<String>> memberCqNamesMap = new TreeMap<>(); + Map<String, List<String>> errorMessageNodes = new HashMap<>(); + Map<String, List<String>> exceptionMessageNodes = new HashMap<>(); + + for (DurableCqNamesResult memberResult : results) { + if (memberResult != null) { + if (memberResult.isSuccessful()) { + memberCqNamesMap.put(memberResult.getMemberNameOrId(), memberResult.getCqNamesList()); + } else { + if (memberResult.isOpPossible()) { + groupByMessage(memberResult.getExceptionMessage(), memberResult.getMemberNameOrId(), + exceptionMessageNodes); + } else { + groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), + errorMessageNodes); + } + } + } + } + + if (!memberCqNamesMap.isEmpty()) { + TabularResultData table = ResultBuilder.createTabularResultData(); + Set<String> members = memberCqNamesMap.keySet(); + + for (String member : members) { + boolean isFirst = true; + List<String> cqNames = memberCqNamesMap.get(member); + for (String cqName : cqNames) { + if (isFirst) { + isFirst = false; + table.accumulate(CliStrings.MEMBER, member); + } else { + table.accumulate(CliStrings.MEMBER, ""); + } + table.accumulate(CliStrings.LIST_DURABLE_CQS__NAME, cqName); + } + } + result = ResultBuilder.buildResult(table); + } else { + String errorHeader = + CliStrings.format(CliStrings.LIST_DURABLE_CQS__FAILURE__HEADER, durableClientId); + result = ResultBuilder.buildResult( + buildFailureData(null, exceptionMessageNodes, errorMessageNodes, errorHeader)); + } + } catch (Exception e) { + result = ResultBuilder.createGemFireErrorResult(e.getMessage()); + } + + return result; + } + + @CliCommand(value = CliStrings.COUNT_DURABLE_CQ_EVENTS, + help = CliStrings.COUNT_DURABLE_CQ_EVENTS__HELP) + @CliMetaData() + @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) + public Result countDurableCqEvents( + @CliOption(key = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CLIENT__ID, mandatory = true, + help = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CLIENT__ID__HELP) final String durableClientId, + @CliOption(key = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CQ__NAME, + help = CliStrings.COUNT_DURABLE_CQ_EVENTS__DURABLE__CQ__NAME__HELP) final String cqName, + @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, + help = CliStrings.COUNT_DURABLE_CQ_EVENTS__MEMBER__HELP, + optionContext = ConverterHint.MEMBERIDNAME) final String[] memberNameOrId, + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + help = CliStrings.COUNT_DURABLE_CQ_EVENTS__GROUP__HELP, + optionContext = ConverterHint.MEMBERGROUP) final String[] group) { + + Result result; + try { + Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId); + + if (targetMembers.isEmpty()) { + return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); + } + + String[] params = new String[2]; + params[0] = durableClientId; + params[1] = cqName; + final ResultCollector<?, ?> rc = + CliUtil.executeFunction(new GetSubscriptionQueueSizeFunction(), params, targetMembers); + final List<SubscriptionQueueSizeResult> funcResults = + (List<SubscriptionQueueSizeResult>) rc.getResult(); + + String queueSizeColumnName; + + if (cqName != null && !cqName.isEmpty()) { + queueSizeColumnName = CliStrings + .format(CliStrings.COUNT_DURABLE_CQ_EVENTS__SUBSCRIPTION__QUEUE__SIZE__CLIENT, cqName); + } else { + queueSizeColumnName = CliStrings.format( + CliStrings.COUNT_DURABLE_CQ_EVENTS__SUBSCRIPTION__QUEUE__SIZE__CLIENT, durableClientId); + } + result = buildTableResultForQueueSize(funcResults, queueSizeColumnName); + } catch (Exception e) { + result = ResultBuilder.createGemFireErrorResult(e.getMessage()); + } + + return result; + } + + @CliCommand(value = CliStrings.CLOSE_DURABLE_CLIENTS, + help = CliStrings.CLOSE_DURABLE_CLIENTS__HELP) + @CliMetaData() + @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE, + target = Target.QUERY) + public Result closeDurableClient( + @CliOption(key = CliStrings.CLOSE_DURABLE_CLIENTS__CLIENT__ID, mandatory = true, + help = CliStrings.CLOSE_DURABLE_CLIENTS__CLIENT__ID__HELP) final String durableClientId, + @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, + help = CliStrings.CLOSE_DURABLE_CLIENTS__MEMBER__HELP, + optionContext = ConverterHint.MEMBERIDNAME) final String[] memberNameOrId, + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + help = CliStrings.COUNT_DURABLE_CQ_EVENTS__GROUP__HELP, + optionContext = ConverterHint.MEMBERGROUP) final String[] group) { + + Result result; + try { + + Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId); + + if (targetMembers.isEmpty()) { + return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); + } + + final ResultCollector<?, ?> rc = + CliUtil.executeFunction(new CloseDurableClientFunction(), durableClientId, targetMembers); + final List<MemberResult> results = (List<MemberResult>) rc.getResult(); + String failureHeader = + CliStrings.format(CliStrings.CLOSE_DURABLE_CLIENTS__FAILURE__HEADER, durableClientId); + String successHeader = + CliStrings.format(CliStrings.CLOSE_DURABLE_CLIENTS__SUCCESS, durableClientId); + result = buildResult(results, successHeader, failureHeader); + } catch (Exception e) { + result = ResultBuilder.createGemFireErrorResult(e.getMessage()); + } + return result; + } + + + @CliCommand(value = CliStrings.CLOSE_DURABLE_CQS, help = CliStrings.CLOSE_DURABLE_CQS__HELP) + @CliMetaData() + @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE, + target = Target.QUERY) + public Result closeDurableCqs(@CliOption(key = CliStrings.CLOSE_DURABLE_CQS__DURABLE__CLIENT__ID, + mandatory = true, + help = CliStrings.CLOSE_DURABLE_CQS__DURABLE__CLIENT__ID__HELP) final String durableClientId, + + @CliOption(key = CliStrings.CLOSE_DURABLE_CQS__NAME, mandatory = true, + help = CliStrings.CLOSE_DURABLE_CQS__NAME__HELP) final String cqName, + + @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, + help = CliStrings.CLOSE_DURABLE_CQS__MEMBER__HELP, + optionContext = ConverterHint.MEMBERIDNAME) final String[] memberNameOrId, + + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + help = CliStrings.CLOSE_DURABLE_CQS__GROUP__HELP, + optionContext = ConverterHint.MEMBERGROUP) final String[] group) { + Result result; + try { + Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId); + + if (targetMembers.isEmpty()) { + return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); + } + + String[] params = new String[2]; + params[0] = durableClientId; + params[1] = cqName; + + final ResultCollector<?, ?> rc = + CliUtil.executeFunction(new CloseDurableCqFunction(), params, targetMembers); + final List<MemberResult> results = (List<MemberResult>) rc.getResult(); + String failureHeader = + CliStrings.format(CliStrings.CLOSE_DURABLE_CQS__FAILURE__HEADER, cqName, durableClientId); + String successHeader = + CliStrings.format(CliStrings.CLOSE_DURABLE_CQS__SUCCESS, cqName, durableClientId); + result = buildResult(results, successHeader, failureHeader); + } catch (Exception e) { + result = ResultBuilder.createGemFireErrorResult(e.getMessage()); + } + return result; + } + + + private Result buildResult(List<MemberResult> results, String successHeader, + String failureHeader) { + Result result; + boolean failure = true; + boolean partialFailure = false; + Map<String, List<String>> errorMap = new HashMap<>(); + Map<String, List<String>> successMap = new HashMap<>(); + Map<String, List<String>> exceptionMap = new HashMap<>(); + + /* + * Aggregate the results from the members + */ + for (MemberResult memberResult : results) { + + if (memberResult.isSuccessful()) { + failure = false; + groupByMessage(memberResult.getSuccessMessage(), memberResult.getMemberNameOrId(), + successMap); + } else { + + if (memberResult.isOpPossible()) { + partialFailure = true; + groupByMessage(memberResult.getExceptionMessage(), memberResult.getMemberNameOrId(), + exceptionMap); + + } else { + groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), + errorMap); + } + } + } + + if (!failure && !partialFailure) { + result = ResultBuilder.buildResult(buildSuccessData(successMap)); + } else { + result = ResultBuilder + .buildResult(buildFailureData(successMap, exceptionMap, errorMap, failureHeader)); + } + return result; + } + + private Result buildTableResultForQueueSize(List<SubscriptionQueueSizeResult> results, + String queueSizeColumnName) { + Result result; + boolean failure = true; + + Map<String, List<String>> failureMap = new HashMap<>(); + Map<String, Long> memberQueueSizeTable = new TreeMap<>(); + + /* + * Aggregate the results from the members + */ + for (SubscriptionQueueSizeResult memberResult : results) { + + if (memberResult.isSuccessful()) { + failure = false; + memberQueueSizeTable.put(memberResult.getMemberNameOrId(), + memberResult.getSubscriptionQueueSize()); + } else { + groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), + failureMap); + } + } + + if (!failure) { + TabularResultData table = ResultBuilder.createTabularResultData(); + + Set<String> members = memberQueueSizeTable.keySet(); + + for (String member : members) { + long queueSize = memberQueueSizeTable.get(member); + table.accumulate(CliStrings.MEMBER, member); + table.accumulate(queueSizeColumnName, queueSize); + } + result = ResultBuilder.buildResult(table); + + } else { + ErrorResultData erd = ResultBuilder.createErrorResultData(); + buildErrorResult(erd, failureMap); + result = ResultBuilder.buildResult(erd); + } + return result; + } + + private void groupByMessage(String message, String memberNameOrId, + Map<String, List<String>> map) { + List<String> members = map.get(message); + + if (members == null) { + members = new LinkedList<>(); + } + members.add(memberNameOrId); + map.put(message, members); + } + + + private InfoResultData buildSuccessData(Map<String, List<String>> successMap) { + InfoResultData ird = ResultBuilder.createInfoResultData(); + Set<String> successMessages = successMap.keySet(); + + for (String successMessage : successMessages) { + ird.addLine(CliStrings.format(CliStrings.ACTION_SUCCEEDED_ON_MEMBER, successMessage)); + + List<String> successfulMembers = successMap.get(successMessage); + int num = 0; + for (String member : successfulMembers) { + ird.addLine("" + ++num + "." + member); + } + ird.addLine("\n"); + } + return ird; + } + + private ErrorResultData buildFailureData(Map<String, List<String>> successMap, + Map<String, List<String>> exceptionMap, Map<String, List<String>> errorMap, + String errorHeader) { + ErrorResultData erd = ResultBuilder.createErrorResultData(); + buildErrorResult(erd, successMap); + erd.addLine("\n"); + erd.addLine(errorHeader); + buildErrorResult(erd, exceptionMap); + buildErrorResult(erd, errorMap); + return erd; + } + + private void buildErrorResult(ErrorResultData erd, Map<String, List<String>> resultMap) { + if (resultMap != null && !resultMap.isEmpty()) { + Set<String> messages = resultMap.keySet(); + + for (String message : messages) { + erd.addLine("\n"); + erd.addLine(message); + erd.addLine(CliStrings.OCCURRED_ON_MEMBERS); + List<String> members = resultMap.get(message); + int num = 0; + for (String member : members) { + ++num; + erd.addLine("" + num + "." + member); + } + } + } + } +} +
http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommandsResultBuilder.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommandsResultBuilder.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommandsResultBuilder.java deleted file mode 100644 index 743602a..0000000 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DurableClientCommandsResultBuilder.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import org.apache.geode.management.cli.Result; -import org.apache.geode.management.internal.cli.domain.MemberResult; -import org.apache.geode.management.internal.cli.domain.SubscriptionQueueSizeResult; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.ErrorResultData; -import org.apache.geode.management.internal.cli.result.InfoResultData; -import org.apache.geode.management.internal.cli.result.ResultBuilder; -import org.apache.geode.management.internal.cli.result.TabularResultData; - -public class DurableClientCommandsResultBuilder { - public Result buildResult(List<MemberResult> results, String successHeader, - String failureHeader) { - Result result; - boolean failure = true; - boolean partialFailure = false; - Map<String, List<String>> errorMap = new HashMap<>(); - Map<String, List<String>> successMap = new HashMap<>(); - Map<String, List<String>> exceptionMap = new HashMap<>(); - - // Aggregate the results from the members - for (MemberResult memberResult : results) { - if (memberResult.isSuccessful()) { - failure = false; - groupByMessage(memberResult.getSuccessMessage(), memberResult.getMemberNameOrId(), - successMap); - } else { - if (memberResult.isOpPossible()) { - partialFailure = true; - groupByMessage(memberResult.getExceptionMessage(), memberResult.getMemberNameOrId(), - exceptionMap); - } else { - groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), - errorMap); - } - } - } - - if (!failure && !partialFailure) { - result = ResultBuilder.buildResult(buildSuccessData(successMap)); - } else { - result = ResultBuilder - .buildResult(buildFailureData(successMap, exceptionMap, errorMap, failureHeader)); - } - return result; - } - - Result buildTableResultForQueueSize(List<SubscriptionQueueSizeResult> results, - String queueSizeColumnName) { - Result result; - boolean failure = true; - - Map<String, List<String>> failureMap = new HashMap<>(); - Map<String, Long> memberQueueSizeTable = new TreeMap<>(); - - // Aggregate the results from the members - for (SubscriptionQueueSizeResult memberResult : results) { - if (memberResult.isSuccessful()) { - failure = false; - memberQueueSizeTable.put(memberResult.getMemberNameOrId(), - memberResult.getSubscriptionQueueSize()); - } else { - groupByMessage(memberResult.getErrorMessage(), memberResult.getMemberNameOrId(), - failureMap); - } - } - - if (!failure) { - TabularResultData table = ResultBuilder.createTabularResultData(); - Set<String> members = memberQueueSizeTable.keySet(); - - for (String member : members) { - long queueSize = memberQueueSizeTable.get(member); - table.accumulate(CliStrings.MEMBER, member); - table.accumulate(queueSizeColumnName, queueSize); - } - result = ResultBuilder.buildResult(table); - } else { - ErrorResultData erd = ResultBuilder.createErrorResultData(); - buildErrorResult(erd, failureMap); - result = ResultBuilder.buildResult(erd); - } - return result; - } - - void groupByMessage(String message, String memberNameOrId, Map<String, List<String>> map) { - List<String> members = map.get(message); - if (members == null) { - members = new LinkedList<>(); - } - members.add(memberNameOrId); - map.put(message, members); - } - - - private InfoResultData buildSuccessData(Map<String, List<String>> successMap) { - InfoResultData ird = ResultBuilder.createInfoResultData(); - Set<String> successMessages = successMap.keySet(); - - for (String successMessage : successMessages) { - ird.addLine(CliStrings.format(CliStrings.ACTION_SUCCEEDED_ON_MEMBER, successMessage)); - List<String> successfulMembers = successMap.get(successMessage); - int num = 0; - for (String member : successfulMembers) { - ird.addLine("" + ++num + "." + member); - } - ird.addLine("\n"); - } - return ird; - } - - ErrorResultData buildFailureData(Map<String, List<String>> successMap, - Map<String, List<String>> exceptionMap, Map<String, List<String>> errorMap, - String errorHeader) { - ErrorResultData erd = ResultBuilder.createErrorResultData(); - buildErrorResult(erd, successMap); - erd.addLine("\n"); - erd.addLine(errorHeader); - buildErrorResult(erd, exceptionMap); - buildErrorResult(erd, errorMap); - return erd; - } - - private void buildErrorResult(ErrorResultData erd, Map<String, List<String>> resultMap) { - if (resultMap != null && !resultMap.isEmpty()) { - Set<String> messages = resultMap.keySet(); - - for (String message : messages) { - erd.addLine("\n"); - erd.addLine(message); - erd.addLine(CliStrings.OCCURRED_ON_MEMBERS); - List<String> members = resultMap.get(message); - int num = 0; - for (String member : members) { - ++num; - erd.addLine("" + num + "." + member); - } - } - } - } -} http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java deleted file mode 100644 index dad9742..0000000 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExecuteFunctionCommand.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * 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 java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - -import org.apache.commons.lang.BooleanUtils; -import org.springframework.shell.core.annotation.CliCommand; -import org.springframework.shell.core.annotation.CliOption; - -import org.apache.geode.cache.Region; -import org.apache.geode.cache.execute.Execution; -import org.apache.geode.cache.execute.Function; -import org.apache.geode.cache.execute.FunctionException; -import org.apache.geode.cache.execute.FunctionService; -import org.apache.geode.cache.execute.ResultCollector; -import org.apache.geode.distributed.DistributedMember; -import org.apache.geode.internal.ClassPathLoader; -import org.apache.geode.internal.cache.InternalCache; -import org.apache.geode.management.DistributedRegionMXBean; -import org.apache.geode.management.ManagementService; -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.internal.MBeanJMXAdapter; -import org.apache.geode.management.internal.cli.CliUtil; -import org.apache.geode.management.internal.cli.LogWrapper; -import org.apache.geode.management.internal.cli.functions.UserFunctionExecution; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.CompositeResultData; -import org.apache.geode.management.internal.cli.result.ErrorResultData; -import org.apache.geode.management.internal.cli.result.ResultBuilder; -import org.apache.geode.management.internal.cli.result.TabularResultData; -import org.apache.geode.management.internal.security.ResourceOperation; -import org.apache.geode.security.ResourcePermission; - -public class ExecuteFunctionCommand implements GfshCommand { - @CliCommand(value = CliStrings.EXECUTE_FUNCTION, help = CliStrings.EXECUTE_FUNCTION__HELP) - @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_FUNCTION}) - @ResourceOperation(resource = ResourcePermission.Resource.DATA, - operation = ResourcePermission.Operation.WRITE) - public Result executeFunction( - // TODO: Add optioncontext for functionID - @CliOption(key = CliStrings.EXECUTE_FUNCTION__ID, mandatory = true, - help = CliStrings.EXECUTE_FUNCTION__ID__HELP) String functionId, - @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, - optionContext = ConverterHint.MEMBERGROUP, - help = CliStrings.EXECUTE_FUNCTION__ONGROUPS__HELP) String[] onGroups, - @CliOption(key = CliStrings.MEMBER, optionContext = ConverterHint.MEMBERIDNAME, - help = CliStrings.EXECUTE_FUNCTION__ONMEMBER__HELP) String onMember, - @CliOption(key = CliStrings.EXECUTE_FUNCTION__ONREGION, - optionContext = ConverterHint.REGION_PATH, - help = CliStrings.EXECUTE_FUNCTION__ONREGION__HELP) String onRegion, - @CliOption(key = CliStrings.EXECUTE_FUNCTION__ARGUMENTS, - help = CliStrings.EXECUTE_FUNCTION__ARGUMENTS__HELP) String[] arguments, - @CliOption(key = CliStrings.EXECUTE_FUNCTION__RESULTCOLLECTOR, - help = CliStrings.EXECUTE_FUNCTION__RESULTCOLLECTOR__HELP) String resultCollector, - @CliOption(key = CliStrings.EXECUTE_FUNCTION__FILTER, - help = CliStrings.EXECUTE_FUNCTION__FILTER__HELP) String filterString) { - CompositeResultData executeFunctionResultTable = ResultBuilder.createCompositeResultData(); - TabularResultData resultTable = executeFunctionResultTable.addSection().addTable("Table1"); - String headerText = "Execution summary"; - resultTable.setHeader(headerText); - ResultCollector resultCollectorInstance = null; - Set<String> filters = new HashSet<>(); - Execution execution; - if (functionId != null) { - functionId = functionId.trim(); - } - if (onRegion != null) { - onRegion = onRegion.trim(); - } - if (onMember != null) { - onMember = onMember.trim(); - } - if (filterString != null) { - filterString = filterString.trim(); - } - - try { - // validate otherwise return right away. no need to process anything - if (functionId == null || functionId.length() == 0) { - ErrorResultData errorResultData = - ResultBuilder.createErrorResultData().setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) - .addLine(CliStrings.EXECUTE_FUNCTION__MSG__MISSING_FUNCTIONID); - return ResultBuilder.buildResult(errorResultData); - } - - if (moreThanOneIsTrue(onRegion != null, onMember != null, onGroups != null)) { - // Provide Only one of region/member/groups - ErrorResultData errorResultData = - ResultBuilder.createErrorResultData().setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) - .addLine(CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS); - return ResultBuilder.buildResult(errorResultData); - } else if ((onRegion == null || onRegion.length() == 0) && (filterString != null)) { - ErrorResultData errorResultData = ResultBuilder.createErrorResultData() - .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) - .addLine(CliStrings.EXECUTE_FUNCTION__MSG__MEMBER_SHOULD_NOT_HAVE_FILTER_FOR_EXECUTION); - return ResultBuilder.buildResult(errorResultData); - } - - InternalCache cache = getCache(); - - if (resultCollector != null) { - resultCollectorInstance = - (ResultCollector) ClassPathLoader.getLatest().forName(resultCollector).newInstance(); - } - - if (filterString != null && filterString.length() > 0) { - filters.add(filterString); - } - - if (onRegion == null && onMember == null && onGroups == null) { - // run function on all the members excluding locators bug#46113 - // if user wish to execute on locator then he can choose --member or --group option - Set<DistributedMember> dsMembers = CliUtil.getAllNormalMembers(cache); - if (dsMembers.size() > 0) { - new UserFunctionExecution(); - LogWrapper.getInstance().info(CliStrings - .format(CliStrings.EXECUTE_FUNCTION__MSG__EXECUTING_0_ON_ENTIRE_DS, functionId)); - for (DistributedMember member : dsMembers) { - executeAndGetResults(functionId, null, resultCollector, arguments, member, resultTable, - null); - } - return ResultBuilder.buildResult(resultTable); - } else { - return ResultBuilder - .createUserErrorResult(CliStrings.EXECUTE_FUNCTION__MSG__DS_HAS_NO_MEMBERS); - } - } else if (onRegion != null && onRegion.length() > 0) { - if (cache.getRegion(onRegion) == null) { - // find a member where region is present - DistributedRegionMXBean bean = ManagementService.getManagementService(getCache()) - .getDistributedRegionMXBean(onRegion); - if (bean == null) { - bean = ManagementService.getManagementService(getCache()) - .getDistributedRegionMXBean(Region.SEPARATOR + onRegion); - - if (bean == null) { - return ResultBuilder.createGemFireErrorResult(CliStrings - .format(CliStrings.EXECUTE_FUNCTION__MSG__MXBEAN_0_FOR_NOT_FOUND, onRegion)); - } - } - - DistributedMember member = null; - String[] membersName = bean.getMembers(); - Set<DistributedMember> dsMembers = CliUtil.getAllMembers(cache); - Iterator it = dsMembers.iterator(); - boolean matchFound = false; - - if (membersName.length > 0) { - while (it.hasNext() && !matchFound) { - DistributedMember dsmember = (DistributedMember) it.next(); - for (String memberName : membersName) { - if (MBeanJMXAdapter.getMemberNameOrId(dsmember).equals(memberName)) { - member = dsmember; - matchFound = true; - break; - } - } - } - } - if (matchFound) { - executeAndGetResults(functionId, filterString, resultCollector, arguments, member, - resultTable, onRegion); - return ResultBuilder.buildResult(resultTable); - } else { - return ResultBuilder.createGemFireErrorResult(CliStrings.format( - CliStrings.EXECUTE_FUNCTION__MSG__NO_ASSOCIATED_MEMBER_REGION, " " + onRegion)); - } - } else { - execution = FunctionService.onRegion(cache.getRegion(onRegion)); - if (execution != null) { - if (resultCollectorInstance != null) { - execution = execution.withCollector(resultCollectorInstance); - } - if (filters.size() > 0) { - execution = execution.withFilter(filters); - } - if (arguments != null && arguments.length > 0) { - execution = execution.setArguments(arguments); - } - - try { - List<Object> results = (List<Object>) execution.execute(functionId).getResult(); - if (results.size() > 0) { - StringBuilder strResult = new StringBuilder(); - for (Object obj : results) { - strResult.append(obj); - } - toTabularResultData(resultTable, - cache.getDistributedSystem().getDistributedMember().getId(), - strResult.toString()); - } - return ResultBuilder.buildResult(resultTable); - } catch (FunctionException e) { - return ResultBuilder.createGemFireErrorResult(CliStrings.format( - CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_REGION_1_DETAILS_2, - functionId, onRegion, e.getMessage())); - } - } else { - return ResultBuilder.createGemFireErrorResult(CliStrings.format( - CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_REGION_1_DETAILS_2, - functionId, onRegion, - CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR)); - } - } - } else if (onGroups != null) { - // execute on group members - Set<DistributedMember> dsMembers = new HashSet<>(); - for (String grp : onGroups) { - dsMembers.addAll(cache.getDistributedSystem().getGroupMembers(grp)); - } - - if (dsMembers.size() > 0) { - for (DistributedMember member : dsMembers) { - executeAndGetResults(functionId, filterString, resultCollector, arguments, member, - resultTable, onRegion); - } - return ResultBuilder.buildResult(resultTable); - } else { - StringBuilder grps = new StringBuilder(); - for (String grp : onGroups) { - grps.append(grp); - grps.append(", "); - } - return ResultBuilder.createUserErrorResult( - CliStrings.format(CliStrings.EXECUTE_FUNCTION__MSG__GROUPS_0_HAS_NO_MEMBERS, - grps.toString().substring(0, grps.toString().length() - 1))); - } - } else if (onMember != null && onMember.length() > 0) { - DistributedMember member = CliUtil.getDistributedMemberByNameOrId(onMember); // fix for bug - // 45658 - if (member != null) { - executeAndGetResults(functionId, filterString, resultCollector, arguments, member, - resultTable, onRegion); - } else { - toTabularResultData(resultTable, onMember, CliStrings - .format(CliStrings.EXECUTE_FUNCTION__MSG__NO_ASSOCIATED_MEMBER + " " + onMember)); - } - return ResultBuilder.buildResult(resultTable); - } - } catch (Exception e) { - ErrorResultData errorResultData = ResultBuilder.createErrorResultData() - .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(e.getMessage()); - return ResultBuilder.buildResult(errorResultData); - } - return null; - } - - private boolean moreThanOneIsTrue(Boolean... values) { - return Stream.of(values).mapToInt(BooleanUtils::toInteger).sum() > 1; - } - - private void executeAndGetResults(String functionId, String filterString, String resultCollector, - String[] arguments, DistributedMember member, TabularResultData resultTable, - String onRegion) { - StringBuilder resultMessage = new StringBuilder(); - try { - Function function = new UserFunctionExecution(); - Object[] args = new Object[5]; - args[0] = functionId; - if (filterString != null) { - args[1] = filterString; - } - if (resultCollector != null) { - args[2] = resultCollector; - } - if (arguments != null && arguments.length > 0) { - args[3] = ""; - for (String str : arguments) { - // send via CSV separated value format - if (str != null) { - args[3] = args[3] + str + ","; - } - } - } - args[4] = onRegion; - - Execution execution = FunctionService.onMember(member).setArguments(args); - if (execution != null) { - List<Object> results = (List<Object>) execution.execute(function).getResult(); - if (results != null) { - for (Object resultObj : results) { - if (resultObj != null) { - if (resultObj instanceof String) { - resultMessage.append(((String) resultObj)); - } else if (resultObj instanceof Exception) { - resultMessage.append(((Exception) resultObj).getMessage()); - } else { - resultMessage.append(resultObj); - } - } - } - } - toTabularResultData(resultTable, member.getId(), resultMessage.toString()); - } else { - toTabularResultData(resultTable, member.getId(), - CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR); - } - } catch (Exception e) { - resultMessage.append(CliStrings.format( - CliStrings.EXECUTE_FUNCTION__MSG__COULD_NOT_EXECUTE_FUNCTION_0_ON_MEMBER_1_ERROR_2, - functionId, member.getId(), e.getMessage())); - toTabularResultData(resultTable, member.getId(), resultMessage.toString()); - } - } - - private void toTabularResultData(TabularResultData table, String memberId, String memberResult) { - table.accumulate("Member ID/Name", memberId); - table.accumulate("Function Execution Result", memberResult); - } -} http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java deleted file mode 100644 index 672ec88..0000000 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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 java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.shell.core.annotation.CliCommand; -import org.springframework.shell.core.annotation.CliOption; - -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.internal.cli.AbstractCliAroundInterceptor; -import org.apache.geode.management.internal.cli.CliUtil; -import org.apache.geode.management.internal.cli.GfshParseResult; -import org.apache.geode.management.internal.cli.functions.CliFunctionResult; -import org.apache.geode.management.internal.cli.functions.ExportConfigFunction; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.InfoResultData; -import org.apache.geode.management.internal.cli.result.ResultBuilder; -import org.apache.geode.management.internal.cli.shell.Gfsh; -import org.apache.geode.management.internal.security.ResourceOperation; -import org.apache.geode.security.ResourcePermission; - -public class ExportConfigCommand implements GfshCommand { - private final ExportConfigFunction exportConfigFunction = new ExportConfigFunction(); - - /** - * Export the cache configuration in XML format. - * - * @param member Member for which to write the configuration - * @param group Group or groups for which to write the configuration - * @return Results of the attempt to write the configuration - */ - @CliCommand(value = {CliStrings.EXPORT_CONFIG}, help = CliStrings.EXPORT_CONFIG__HELP) - @CliMetaData( - interceptor = "org.apache.geode.management.internal.cli.commands.ExportConfigCommand$Interceptor", - relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG}) - @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER, - operation = ResourcePermission.Operation.READ) - public Result exportConfig( - @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, - optionContext = ConverterHint.ALL_MEMBER_IDNAME, - help = CliStrings.EXPORT_CONFIG__MEMBER__HELP) String[] member, - @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, - optionContext = ConverterHint.MEMBERGROUP, - help = CliStrings.EXPORT_CONFIG__GROUP__HELP) String[] group, - @CliOption(key = {CliStrings.EXPORT_CONFIG__DIR}, - help = CliStrings.EXPORT_CONFIG__DIR__HELP) String dir) { - InfoResultData infoData = ResultBuilder.createInfoResultData(); - - Set<DistributedMember> targetMembers = CliUtil.findMembers(group, member); - if (targetMembers.isEmpty()) { - return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); - } - - try { - ResultCollector<?, ?> rc = - CliUtil.executeFunction(this.exportConfigFunction, null, targetMembers); - List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult()); - - for (CliFunctionResult result : results) { - if (result.getThrowable() != null) { - infoData.addLine(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__EXCEPTION, - result.getMemberIdOrName(), result.getThrowable())); - } else if (result.isSuccessful()) { - String cacheFileName = result.getMemberIdOrName() + "-cache.xml"; - String propsFileName = result.getMemberIdOrName() + "-gf.properties"; - String[] fileContent = (String[]) result.getSerializables(); - infoData.addAsFile(cacheFileName, fileContent[0], "Downloading Cache XML file: {0}", - false); - infoData.addAsFile(propsFileName, fileContent[1], "Downloading properties file: {0}", - false); - } - } - return ResultBuilder.buildResult(infoData); - } catch (VirtualMachineError e) { - SystemFailure.initiateFailure(e); - throw e; - } catch (Throwable th) { - SystemFailure.checkFailure(); - th.printStackTrace(System.err); - return ResultBuilder - .createGemFireErrorResult(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__EXCEPTION, - th.getClass().getName() + ": " + th.getMessage())); - } - } - - /** - * Interceptor used by gfsh to intercept execution of export config command at "shell". - */ - public static class Interceptor extends AbstractCliAroundInterceptor { - private String saveDirString; - - @Override - public Result preExecution(GfshParseResult parseResult) { - Map<String, String> paramValueMap = parseResult.getParamValueStrings(); - String dir = paramValueMap.get("dir"); - dir = (dir == null) ? null : dir.trim(); - - File saveDirFile = new File("."); - if (dir != null && !dir.isEmpty()) { - saveDirFile = new File(dir); - if (saveDirFile.exists()) { - if (!saveDirFile.isDirectory()) - return ResultBuilder.createGemFireErrorResult( - CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_A_DIRECTORY, dir)); - } else if (!saveDirFile.mkdirs()) { - return ResultBuilder.createGemFireErrorResult( - CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__CANNOT_CREATE_DIR, dir)); - } - } - try { - if (!saveDirFile.canWrite()) { - return ResultBuilder.createGemFireErrorResult(CliStrings.format( - CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, saveDirFile.getCanonicalPath())); - } - } catch (IOException ioex) { - return ResultBuilder.createGemFireErrorResult( - CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, saveDirFile.getName())); - } - - saveDirString = saveDirFile.getAbsolutePath(); - return ResultBuilder.createInfoResult("OK"); - } - - @Override - public Result postExecution(GfshParseResult parseResult, Result commandResult, Path tempFile) { - if (commandResult.hasIncomingFiles()) { - try { - commandResult.saveIncomingFiles(saveDirString); - } catch (IOException ioex) { - Gfsh.getCurrentInstance().logSevere("Unable to export config", ioex); - } - } - return commandResult; - } - } -} http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportOfflineDiskStoreCommand.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportOfflineDiskStoreCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportOfflineDiskStoreCommand.java deleted file mode 100644 index c704364..0000000 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportOfflineDiskStoreCommand.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 java.io.File; - -import org.springframework.shell.core.annotation.CliCommand; -import org.springframework.shell.core.annotation.CliOption; - -import org.apache.geode.SystemFailure; -import org.apache.geode.internal.cache.DiskStoreImpl; -import org.apache.geode.management.cli.CliMetaData; -import org.apache.geode.management.cli.Result; -import org.apache.geode.management.internal.cli.LogWrapper; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.ResultBuilder; - -public class ExportOfflineDiskStoreCommand implements GfshCommand { - @CliCommand(value = CliStrings.EXPORT_OFFLINE_DISK_STORE, - help = CliStrings.EXPORT_OFFLINE_DISK_STORE__HELP) - @CliMetaData(shellOnly = true, relatedTopic = {CliStrings.TOPIC_GEODE_DISKSTORE}) - public Result exportOfflineDiskStore( - @CliOption(key = CliStrings.EXPORT_OFFLINE_DISK_STORE__DISKSTORENAME, mandatory = true, - help = CliStrings.EXPORT_OFFLINE_DISK_STORE__DISKSTORENAME__HELP) String diskStoreName, - @CliOption(key = CliStrings.EXPORT_OFFLINE_DISK_STORE__DISKDIRS, mandatory = true, - help = CliStrings.EXPORT_OFFLINE_DISK_STORE__DISKDIRS__HELP) String[] diskDirs, - @CliOption(key = CliStrings.EXPORT_OFFLINE_DISK_STORE__DIR, mandatory = true, - help = CliStrings.EXPORT_OFFLINE_DISK_STORE__DIR__HELP) String dir) { - - try { - final File[] dirs = new File[diskDirs.length]; - for (int i = 0; i < diskDirs.length; i++) { - dirs[i] = new File((diskDirs[i])); - } - - File output = new File(dir); - - // Note, this can consume a lot of memory, so this should - // not be moved to a separate process unless we provide a way for the user - // to configure the size of that process. - DiskStoreImpl.exportOfflineSnapshot(diskStoreName, dirs, output); - String resultString = - CliStrings.format(CliStrings.EXPORT_OFFLINE_DISK_STORE__SUCCESS, diskStoreName, dir); - return ResultBuilder.createInfoResult(resultString); - } catch (VirtualMachineError e) { - SystemFailure.initiateFailure(e); - throw e; - } catch (Throwable th) { - SystemFailure.checkFailure(); - LogWrapper.getInstance().warning(th.getMessage(), th); - return ResultBuilder.createGemFireErrorResult(CliStrings - .format(CliStrings.EXPORT_OFFLINE_DISK_STORE__ERROR, diskStoreName, th.toString())); - } - } -} http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportStackTraceCommand.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportStackTraceCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportStackTraceCommand.java deleted file mode 100644 index 4f8693d..0000000 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportStackTraceCommand.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.zip.GZIPInputStream; - -import org.springframework.shell.core.annotation.CliCommand; -import org.springframework.shell.core.annotation.CliOption; - -import org.apache.geode.cache.execute.ResultCollector; -import org.apache.geode.distributed.DistributedMember; -import org.apache.geode.distributed.internal.InternalDistributedSystem; -import org.apache.geode.internal.cache.InternalCache; -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.internal.cli.CliUtil; -import org.apache.geode.management.internal.cli.domain.StackTracesPerMember; -import org.apache.geode.management.internal.cli.functions.GetStackTracesFunction; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.InfoResultData; -import org.apache.geode.management.internal.cli.result.ResultBuilder; -import org.apache.geode.management.internal.security.ResourceOperation; -import org.apache.geode.security.ResourcePermission; - -public class ExportStackTraceCommand implements GfshCommand { - private final GetStackTracesFunction getStackTracesFunction = new GetStackTracesFunction(); - - /** - * Current implementation supports writing it to a file and returning the location of the file - */ - @CliCommand(value = CliStrings.EXPORT_STACKTRACE, help = CliStrings.EXPORT_STACKTRACE__HELP) - @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_DEBUG_UTIL}) - @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER, - operation = ResourcePermission.Operation.READ) - public Result exportStackTrace(@CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, - optionContext = ConverterHint.ALL_MEMBER_IDNAME, - help = CliStrings.EXPORT_STACKTRACE__HELP) String[] memberNameOrId, - - @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, - optionContext = ConverterHint.ALL_MEMBER_IDNAME, help = CliStrings.GROUP) String[] group, - - @CliOption(key = CliStrings.EXPORT_STACKTRACE__FILE, - help = CliStrings.EXPORT_STACKTRACE__FILE__HELP) String fileName, - - @CliOption(key = CliStrings.EXPORT_STACKTRACE__FAIL__IF__FILE__PRESENT, - unspecifiedDefaultValue = "false", - help = CliStrings.EXPORT_STACKTRACE__FAIL__IF__FILE__PRESENT__HELP) boolean failIfFilePresent) { - - Result result; - StringBuilder filePrefix = new StringBuilder("stacktrace"); - - if (fileName == null) { - fileName = filePrefix.append("_").append(System.currentTimeMillis()).toString(); - } - final File outFile = new File(fileName); - try { - if (outFile.exists() && failIfFilePresent) { - return ResultBuilder.createShellClientErrorResult(CliStrings.format( - CliStrings.EXPORT_STACKTRACE__ERROR__FILE__PRESENT, outFile.getCanonicalPath())); - } - - - InternalCache cache = getCache(); - InternalDistributedSystem ads = cache.getInternalDistributedSystem(); - - InfoResultData resultData = ResultBuilder.createInfoResultData(); - - Map<String, byte[]> dumps = new HashMap<>(); - Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId); - if (targetMembers.isEmpty()) { - return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); - } - - ResultCollector<?, ?> rc = - CliUtil.executeFunction(getStackTracesFunction, null, targetMembers); - ArrayList<Object> resultList = (ArrayList<Object>) rc.getResult(); - - for (Object resultObj : resultList) { - if (resultObj instanceof StackTracesPerMember) { - StackTracesPerMember stackTracePerMember = (StackTracesPerMember) resultObj; - dumps.put(stackTracePerMember.getMemberNameOrId(), stackTracePerMember.getStackTraces()); - } - } - - String filePath = writeStacksToFile(dumps, fileName); - resultData.addLine(CliStrings.format(CliStrings.EXPORT_STACKTRACE__SUCCESS, filePath)); - resultData.addLine(CliStrings.EXPORT_STACKTRACE__HOST + ads.getDistributedMember().getHost()); - - result = ResultBuilder.buildResult(resultData); - } catch (IOException ex) { - result = ResultBuilder - .createGemFireErrorResult(CliStrings.EXPORT_STACKTRACE__ERROR + ex.getMessage()); - } - return result; - } - - /*** - * Writes the Stack traces member-wise to a text file - * - * @param dumps - Map containing key : member , value : zipped stack traces - * @param fileName - Name of the file to which the stack-traces are written to - * @return Canonical path of the file which contains the stack-traces - * @throws IOException - */ - private String writeStacksToFile(Map<String, byte[]> dumps, String fileName) throws IOException { - String filePath; - PrintWriter ps; - File outputFile; - - outputFile = new File(fileName); - try (OutputStream os = new FileOutputStream(outputFile)) { - ps = new PrintWriter(os); - - for (Map.Entry<String, byte[]> entry : dumps.entrySet()) { - ps.append("*** Stack-trace for member ").append(entry.getKey()).append(" ***"); - ps.flush(); - GZIPInputStream zipIn = new GZIPInputStream(new ByteArrayInputStream(entry.getValue())); - BufferedInputStream bin = new BufferedInputStream(zipIn); - byte[] buffer = new byte[10000]; - int count; - while ((count = bin.read(buffer)) != -1) { - os.write(buffer, 0, count); - } - ps.append('\n'); - } - ps.flush(); - filePath = outputFile.getCanonicalPath(); - } - - return filePath; - } -} http://git-wip-us.apache.org/repos/asf/geode/blob/645a32d0/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/FunctionCommands.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/FunctionCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/FunctionCommands.java new file mode 100644 index 0000000..21d89c1 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/FunctionCommands.java @@ -0,0 +1,537 @@ +/* + * 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Stream; + +import org.apache.commons.lang.BooleanUtils; +import org.springframework.shell.core.annotation.CliCommand; +import org.springframework.shell.core.annotation.CliOption; + +import org.apache.geode.SystemFailure; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.execute.Execution; +import org.apache.geode.cache.execute.Function; +import org.apache.geode.cache.execute.FunctionException; +import org.apache.geode.cache.execute.FunctionService; +import org.apache.geode.cache.execute.ResultCollector; +import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.internal.ClassPathLoader; +import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.management.DistributedRegionMXBean; +import org.apache.geode.management.ManagementService; +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.MBeanJMXAdapter; +import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor; +import org.apache.geode.management.internal.cli.CliUtil; +import org.apache.geode.management.internal.cli.GfshParseResult; +import org.apache.geode.management.internal.cli.LogWrapper; +import org.apache.geode.management.internal.cli.functions.CliFunctionResult; +import org.apache.geode.management.internal.cli.functions.ListFunctionFunction; +import org.apache.geode.management.internal.cli.functions.UnregisterFunction; +import org.apache.geode.management.internal.cli.functions.UserFunctionExecution; +import org.apache.geode.management.internal.cli.i18n.CliStrings; +import org.apache.geode.management.internal.cli.result.CompositeResultData; +import org.apache.geode.management.internal.cli.result.ErrorResultData; +import org.apache.geode.management.internal.cli.result.ResultBuilder; +import org.apache.geode.management.internal.cli.result.TabularResultData; +import org.apache.geode.management.internal.security.ResourceOperation; +import org.apache.geode.security.ResourcePermission.Operation; +import org.apache.geode.security.ResourcePermission.Resource; +import org.apache.geode.security.ResourcePermission.Target; + +/** + * @since GemFire 7.0 + */ +@SuppressWarnings("unused") +public class FunctionCommands implements GfshCommand { + + private final ListFunctionFunction listFunctionFunction = new ListFunctionFunction(); + + @CliCommand(value = CliStrings.EXECUTE_FUNCTION, help = CliStrings.EXECUTE_FUNCTION__HELP) + @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_FUNCTION}) + @ResourceOperation(resource = Resource.DATA, operation = Operation.WRITE) + public Result executeFunction( + // TODO: Add optioncontext for functionID + @CliOption(key = CliStrings.EXECUTE_FUNCTION__ID, mandatory = true, + help = CliStrings.EXECUTE_FUNCTION__ID__HELP) String functionId, + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + optionContext = ConverterHint.MEMBERGROUP, + help = CliStrings.EXECUTE_FUNCTION__ONGROUPS__HELP) String[] onGroups, + @CliOption(key = CliStrings.MEMBER, optionContext = ConverterHint.MEMBERIDNAME, + help = CliStrings.EXECUTE_FUNCTION__ONMEMBER__HELP) String onMember, + @CliOption(key = CliStrings.EXECUTE_FUNCTION__ONREGION, + optionContext = ConverterHint.REGION_PATH, + help = CliStrings.EXECUTE_FUNCTION__ONREGION__HELP) String onRegion, + @CliOption(key = CliStrings.EXECUTE_FUNCTION__ARGUMENTS, + help = CliStrings.EXECUTE_FUNCTION__ARGUMENTS__HELP) String[] arguments, + @CliOption(key = CliStrings.EXECUTE_FUNCTION__RESULTCOLLECTOR, + help = CliStrings.EXECUTE_FUNCTION__RESULTCOLLECTOR__HELP) String resultCollector, + @CliOption(key = CliStrings.EXECUTE_FUNCTION__FILTER, + help = CliStrings.EXECUTE_FUNCTION__FILTER__HELP) String filterString) { + + Result result = null; + CompositeResultData executeFunctionResultTable = ResultBuilder.createCompositeResultData(); + TabularResultData resultTable = executeFunctionResultTable.addSection().addTable("Table1"); + String headerText = "Execution summary"; + resultTable.setHeader(headerText); + ResultCollector resultCollectorInstance = null; + Function function; + Set<String> filters = new HashSet<>(); + Execution execution; + if (functionId != null) { + functionId = functionId.trim(); + } + if (onRegion != null) { + onRegion = onRegion.trim(); + } + if (onMember != null) { + onMember = onMember.trim(); + } + if (filterString != null) { + filterString = filterString.trim(); + } + + try { + // validate otherwise return right away. no need to process anything + if (functionId == null || functionId.length() == 0) { + ErrorResultData errorResultData = + ResultBuilder.createErrorResultData().setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) + .addLine(CliStrings.EXECUTE_FUNCTION__MSG__MISSING_FUNCTIONID); + result = ResultBuilder.buildResult(errorResultData); + return result; + } + + if (isMoreThanOneIsTrue(onRegion != null, onMember != null, onGroups != null)) { + // Provide Only one of region/member/groups + ErrorResultData errorResultData = + ResultBuilder.createErrorResultData().setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) + .addLine(CliStrings.EXECUTE_FUNCTION__MSG__OPTIONS); + result = ResultBuilder.buildResult(errorResultData); + return result; + } else if ((onRegion == null || onRegion.length() == 0) && (filterString != null)) { + ErrorResultData errorResultData = ResultBuilder.createErrorResultData() + .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) + .addLine(CliStrings.EXECUTE_FUNCTION__MSG__MEMBER_SHOULD_NOT_HAVE_FILTER_FOR_EXECUTION); + result = ResultBuilder.buildResult(errorResultData); + return result; + } + + InternalCache cache = getCache(); + + if (resultCollector != null) { + resultCollectorInstance = + (ResultCollector) ClassPathLoader.getLatest().forName(resultCollector).newInstance(); + } + + if (filterString != null && filterString.length() > 0) { + filters.add(filterString); + } + + if (onRegion == null && onMember == null && onGroups == null) { + // run function on all the members excluding locators bug#46113 + // if user wish to execute on locator then he can choose --member or --group option + Set<DistributedMember> dsMembers = CliUtil.getAllNormalMembers(cache); + if (dsMembers.size() > 0) { + function = new UserFunctionExecution(); + LogWrapper.getInstance().info(CliStrings + .format(CliStrings.EXECUTE_FUNCTION__MSG__EXECUTING_0_ON_ENTIRE_DS, functionId)); + for (DistributedMember member : dsMembers) { + executeAndGetResults(functionId, filterString, resultCollector, arguments, cache, + member, resultTable, onRegion); + } + return ResultBuilder.buildResult(resultTable); + } else { + return ResultBuilder + .createUserErrorResult(CliStrings.EXECUTE_FUNCTION__MSG__DS_HAS_NO_MEMBERS); + } + } else if (onRegion != null && onRegion.length() > 0) { + if (cache.getRegion(onRegion) == null) { + // find a member where region is present + DistributedRegionMXBean bean = ManagementService.getManagementService(getCache()) + .getDistributedRegionMXBean(onRegion); + if (bean == null) { + bean = ManagementService.getManagementService(getCache()) + .getDistributedRegionMXBean(Region.SEPARATOR + onRegion); + + if (bean == null) { + return ResultBuilder.createGemFireErrorResult(CliStrings + .format(CliStrings.EXECUTE_FUNCTION__MSG__MXBEAN_0_FOR_NOT_FOUND, onRegion)); + } + } + + DistributedMember member = null; + String[] membersName = bean.getMembers(); + Set<DistributedMember> dsMembers = CliUtil.getAllMembers(cache); + Iterator it = dsMembers.iterator(); + boolean matchFound = false; + + if (membersName.length > 0) { + while (it.hasNext() && !matchFound) { + DistributedMember dsmember = (DistributedMember) it.next(); + for (String memberName : membersName) { + if (MBeanJMXAdapter.getMemberNameOrId(dsmember).equals(memberName)) { + member = dsmember; + matchFound = true; + break; + } + } + } + } + if (matchFound) { + executeAndGetResults(functionId, filterString, resultCollector, arguments, cache, + member, resultTable, onRegion); + return ResultBuilder.buildResult(resultTable); + } else { + return ResultBuilder.createGemFireErrorResult(CliStrings.format( + CliStrings.EXECUTE_FUNCTION__MSG__NO_ASSOCIATED_MEMBER_REGION, " " + onRegion)); + } + } else { + execution = FunctionService.onRegion(cache.getRegion(onRegion)); + if (execution != null) { + if (resultCollectorInstance != null) { + execution = execution.withCollector(resultCollectorInstance); + } + if (filters != null && filters.size() > 0) { + execution = execution.withFilter(filters); + } + if (arguments != null && arguments.length > 0) { + execution = execution.setArguments(arguments); + } + + try { + List<Object> results = (List<Object>) execution.execute(functionId).getResult(); + if (results.size() > 0) { + StringBuilder strResult = new StringBuilder(); + for (Object obj : results) { + strResult.append(obj); + } + toTabularResultData(resultTable, + cache.getDistributedSystem().getDistributedMember().getId(), + strResult.toString()); + } + return ResultBuilder.buildResult(resultTable); + } catch (FunctionException e) { + return ResultBuilder.createGemFireErrorResult(CliStrings.format( + CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_REGION_1_DETAILS_2, + functionId, onRegion, e.getMessage())); + } + } else { + return ResultBuilder.createGemFireErrorResult(CliStrings.format( + CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_REGION_1_DETAILS_2, + functionId, onRegion, + CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR)); + } + } + } else if (onGroups != null) { + // execute on group members + Set<DistributedMember> dsMembers = new HashSet<>(); + for (String grp : onGroups) { + dsMembers.addAll(cache.getDistributedSystem().getGroupMembers(grp)); + } + + StringBuilder successMessage = new StringBuilder(); + if (dsMembers.size() > 0) { + for (DistributedMember member : dsMembers) { + executeAndGetResults(functionId, filterString, resultCollector, arguments, cache, + member, resultTable, onRegion); + } + return ResultBuilder.buildResult(resultTable); + } else { + StringBuilder grps = new StringBuilder(); + for (String grp : onGroups) { + grps.append(grp); + grps.append(", "); + } + return ResultBuilder.createUserErrorResult( + CliStrings.format(CliStrings.EXECUTE_FUNCTION__MSG__GROUPS_0_HAS_NO_MEMBERS, + grps.toString().substring(0, grps.toString().length() - 1))); + } + } else if (onMember != null && onMember.length() > 0) { + DistributedMember member = CliUtil.getDistributedMemberByNameOrId(onMember); // fix for bug + // 45658 + if (member != null) { + executeAndGetResults(functionId, filterString, resultCollector, arguments, cache, member, + resultTable, onRegion); + } else { + toTabularResultData(resultTable, onMember, CliStrings + .format(CliStrings.EXECUTE_FUNCTION__MSG__NO_ASSOCIATED_MEMBER + " " + onMember)); + } + return ResultBuilder.buildResult(resultTable); + } + } catch (Exception e) { + ErrorResultData errorResultData = ResultBuilder.createErrorResultData() + .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(e.getMessage()); + result = ResultBuilder.buildResult(errorResultData); + return result; + } + + return result; + } + + private boolean isMoreThanOneIsTrue(Boolean... values) { + return Stream.of(values).mapToInt(BooleanUtils::toInteger).sum() > 1; + } + + void executeAndGetResults(String functionId, String filterString, String resultCollector, + String[] arguments, InternalCache cache, DistributedMember member, + TabularResultData resultTable, String onRegion) { + StringBuilder resultMessage = new StringBuilder(); + try { + Function function = new UserFunctionExecution(); + Object[] args = new Object[5]; + args[0] = functionId; + if (filterString != null) { + args[1] = filterString; + } + if (resultCollector != null) { + args[2] = resultCollector; + } + if (arguments != null && arguments.length > 0) { + args[3] = ""; + for (String str : arguments) { + // send via CSV separated value format + if (str != null) { + args[3] = args[3] + str + ","; + } + } + } + args[4] = onRegion; + + Execution execution = FunctionService.onMember(member).setArguments(args); + if (execution != null) { + List<Object> results = (List<Object>) execution.execute(function).getResult(); + if (results != null) { + for (Object resultObj : results) { + if (resultObj != null) { + if (resultObj instanceof String) { + resultMessage.append(((String) resultObj)); + } else if (resultObj instanceof Exception) { + resultMessage.append(((Exception) resultObj).getMessage()); + } else { + resultMessage.append(resultObj); + } + } + } + } + toTabularResultData(resultTable, member.getId(), resultMessage.toString()); + } else { + toTabularResultData(resultTable, member.getId(), + CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR); + } + } catch (Exception e) { + resultMessage.append(CliStrings.format( + CliStrings.EXECUTE_FUNCTION__MSG__COULD_NOT_EXECUTE_FUNCTION_0_ON_MEMBER_1_ERROR_2, + functionId, member.getId(), e.getMessage())); + toTabularResultData(resultTable, member.getId(), resultMessage.toString()); + } + } + + protected void toTabularResultData(TabularResultData table, String memberId, + String memberResult) { + String newLine = System.getProperty("line.separator"); + table.accumulate("Member ID/Name", memberId); + table.accumulate("Function Execution Result", memberResult); + } + + @CliCommand(value = CliStrings.DESTROY_FUNCTION, help = CliStrings.DESTROY_FUNCTION__HELP) + @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_FUNCTION}, + interceptor = "org.apache.geode.management.internal.cli.commands.FunctionCommands$Interceptor") + @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE, target = Target.JAR) + // TODO: Add optioncontext for functionId + public Result destroyFunction( + @CliOption(key = CliStrings.DESTROY_FUNCTION__ID, mandatory = true, + help = CliStrings.DESTROY_FUNCTION__HELP) String functionId, + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + optionContext = ConverterHint.MEMBERGROUP, + help = CliStrings.DESTROY_FUNCTION__ONGROUPS__HELP) String[] groups, + @CliOption(key = CliStrings.MEMBER, optionContext = ConverterHint.MEMBERIDNAME, + help = CliStrings.DESTROY_FUNCTION__ONMEMBER__HELP) String memberId) { + Result result; + try { + InternalCache cache = getCache(); + Set<DistributedMember> dsMembers = new HashSet<>(); + if (groups != null && memberId != null) { + return ResultBuilder + .createUserErrorResult(CliStrings.DESTROY_FUNCTION__MSG__PROVIDE_OPTION); + } else if (groups != null && groups.length > 0) { + // execute on group members + for (String grp : groups) { + dsMembers.addAll(cache.getDistributedSystem().getGroupMembers(grp)); + } + @SuppressWarnings("unchecked") + Result results = executeFunction(cache, dsMembers, functionId); + return results; + } else if (memberId != null) { + // execute on member + dsMembers.add(getMember(cache, memberId)); + @SuppressWarnings("unchecked") + Result results = executeFunction(cache, dsMembers, functionId); + return results; + } else { + // no option provided. + @SuppressWarnings("unchecked") + Result results = executeFunction(cache, cache.getMembers(), functionId); + return results; + } + } catch (Exception e) { + ErrorResultData errorResultData = ResultBuilder.createErrorResultData() + .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(e.getMessage()); + result = ResultBuilder.buildResult(errorResultData); + return result; + } + } + + /** + * Interceptor used by gfsh to intercept execution of destroy. + */ + public static class Interceptor extends AbstractCliAroundInterceptor { + @Override + public Result preExecution(GfshParseResult parseResult) { + Map<String, String> paramValueMap = parseResult.getParamValueStrings(); + Set<Entry<String, String>> setEnvMap = paramValueMap.entrySet(); + String onGroup = paramValueMap.get(CliStrings.GROUP); + String onMember = paramValueMap.get(CliStrings.MEMBER); + + if ((onGroup == null && onMember == null)) { + Response response = readYesNo("Do you really want to destroy " + + paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID) + " on entire DS?", Response.NO); + if (response == Response.NO) { + return ResultBuilder.createShellClientAbortOperationResult( + "Aborted destroy of " + paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID)); + } else { + return ResultBuilder + .createInfoResult("Destroying " + paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID)); + } + } else { + return ResultBuilder + .createInfoResult("Destroying " + paramValueMap.get(CliStrings.DESTROY_FUNCTION__ID)); + } + } + } + + Result executeFunction(InternalCache cache, Set<DistributedMember> DsMembers, String functionId) { + // unregister on a set of of members + Function unregisterFunction = new UnregisterFunction(); + FunctionService.registerFunction(unregisterFunction); + List resultList; + + if (DsMembers.isEmpty()) { + return ResultBuilder.createInfoResult("No members for execution"); + } + Object[] obj = new Object[1]; + obj[0] = functionId; + + Execution execution = FunctionService.onMembers(DsMembers).setArguments(obj); + + if (execution == null) { + cache.getLogger().error("executeUnregister execution is null"); + ErrorResultData errorResultData = + ResultBuilder.createErrorResultData().setErrorCode(ResultBuilder.ERRORCODE_DEFAULT) + .addLine(CliStrings.DESTROY_FUNCTION__MSG__CANNOT_EXECUTE); + return (ResultBuilder.buildResult(errorResultData)); + } + try { + resultList = (ArrayList) execution.execute(unregisterFunction).getResult(); + } catch (FunctionException ex) { + ErrorResultData errorResultData = ResultBuilder.createErrorResultData() + .setErrorCode(ResultBuilder.ERRORCODE_DEFAULT).addLine(ex.getMessage()); + return (ResultBuilder.buildResult(errorResultData)); + } + String resultStr = ((String) resultList.get(0)); + if (resultStr.equals("Succeeded in unregistering")) { + StringBuilder members = new StringBuilder(); + for (DistributedMember member : DsMembers) { + members.append(member.getId()); + members.append(","); + } + return ResultBuilder.createInfoResult("Destroyed " + functionId + " Successfully on " + + members.toString().substring(0, members.toString().length() - 1)); + } else { + return ResultBuilder.createInfoResult("Failed in unregistering"); + } + } + + @CliCommand(value = CliStrings.LIST_FUNCTION, help = CliStrings.LIST_FUNCTION__HELP) + @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_FUNCTION}) + @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ) + public Result listFunction( + @CliOption(key = CliStrings.LIST_FUNCTION__MATCHES, + help = CliStrings.LIST_FUNCTION__MATCHES__HELP) String matches, + @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS}, + optionContext = ConverterHint.MEMBERGROUP, + help = CliStrings.LIST_FUNCTION__GROUP__HELP) String[] groups, + @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS}, + optionContext = ConverterHint.MEMBERIDNAME, + help = CliStrings.LIST_FUNCTION__MEMBER__HELP) String[] members) { + TabularResultData tabularData = ResultBuilder.createTabularResultData(); + boolean accumulatedData = false; + + InternalCache cache = getCache(); + + Set<DistributedMember> targetMembers = CliUtil.findMembers(groups, members); + + if (targetMembers.isEmpty()) { + return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE); + } + + try { + ResultCollector<?, ?> rc = + CliUtil.executeFunction(this.listFunctionFunction, new Object[] {matches}, targetMembers); + List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult()); + + for (CliFunctionResult result : results) { + if (result.getThrowable() != null) { + tabularData.accumulate("Member", result.getMemberIdOrName()); + tabularData.accumulate("Function", "<ERROR: " + result.getThrowable().getMessage() + ">"); + accumulatedData = true; + tabularData.setStatus(Status.ERROR); + } else if (result.isSuccessful()) { + String[] strings = (String[]) result.getSerializables(); + Arrays.sort(strings); + for (String string : strings) { + tabularData.accumulate("Member", result.getMemberIdOrName()); + tabularData.accumulate("Function", string); + accumulatedData = true; + } + } + } + + if (!accumulatedData) { + return ResultBuilder + .createInfoResult(CliStrings.LIST_FUNCTION__NO_FUNCTIONS_FOUND_ERROR_MESSAGE); + } + return ResultBuilder.buildResult(tabularData); + } catch (VirtualMachineError e) { + SystemFailure.initiateFailure(e); + throw e; + } catch (Throwable th) { + SystemFailure.checkFailure(); + return ResultBuilder.createGemFireErrorResult( + "Exception while attempting to list functions: " + th.getMessage()); + } + } +}