Return-Path:
X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io
Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io
Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183])
by cust-asf2.ponee.io (Postfix) with ESMTP id DDE33200CF8
for ; Thu, 31 Aug 2017 03:26:11 +0200 (CEST)
Received: by cust-asf.ponee.io (Postfix)
id DC4B816A565; Thu, 31 Aug 2017 01:26:11 +0000 (UTC)
Delivered-To: archive-asf-public@cust-asf.ponee.io
Received: from mail.apache.org (hermes.apache.org [140.211.11.3])
by cust-asf.ponee.io (Postfix) with SMTP id B603C16A560
for ; Thu, 31 Aug 2017 03:26:09 +0200 (CEST)
Received: (qmail 34253 invoked by uid 500); 31 Aug 2017 01:26:08 -0000
Mailing-List: contact commits-help@geode.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: dev@geode.apache.org
Delivered-To: mailing list commits@geode.apache.org
Received: (qmail 30908 invoked by uid 99); 31 Aug 2017 01:25:43 -0000
Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23)
by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 31 Aug 2017 01:25:43 +0000
Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33)
id 1511EF55A4; Thu, 31 Aug 2017 01:25:38 +0000 (UTC)
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
From: dschneider@apache.org
To: commits@geode.apache.org
Date: Thu, 31 Aug 2017 01:25:53 -0000
Message-Id: <01d5f5508e074a5a96f4a3e982be6558@git.apache.org>
In-Reply-To: <4e343206aca34d2495b7c292e7787abc@git.apache.org>
References: <4e343206aca34d2495b7c292e7787abc@git.apache.org>
X-Mailer: ASF-Git Admin Mailer
Subject: [16/47] geode git commit: GEODE-3436: Restore refactoring of
IndexCommands
archived-at: Thu, 31 Aug 2017 01:26:12 -0000
GEODE-3436: Restore refactoring of IndexCommands
* See initial commit GEODE-3262 (ed293e817e547fb5ecd399bf4ba10d694af51e0a)
Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/0dc67f0e
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/0dc67f0e
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/0dc67f0e
Branch: refs/heads/feature/GEODE-3543
Commit: 0dc67f0e7798a38afff906aa26e9bb89ab42b53c
Parents: 3bfe7a2
Author: YehEmily
Authored: Mon Aug 7 12:35:14 2017 -0700
Committer: Jinmei Liao
Committed: Tue Aug 29 09:27:26 2017 -0700
----------------------------------------------------------------------
.../commands/ClearDefinedIndexesCommand.java | 40 ++
.../commands/CreateDefinedIndexesCommand.java | 155 +++++
.../cli/commands/CreateIndexCommand.java | 197 ++++++
.../cli/commands/DefineIndexCommand.java | 95 +++
.../cli/commands/DestroyIndexCommand.java | 174 +++++
.../internal/cli/commands/IndexCommands.java | 668 -------------------
.../internal/cli/commands/IndexDefinition.java | 27 +
.../internal/cli/commands/ListIndexCommand.java | 158 +++++
.../functions/CreateDefinedIndexesFunction.java | 3 +-
.../controllers/IndexCommandsController.java | 13 +-
.../cli/commands/IndexCommandsJUnitTest.java | 223 -------
.../cli/commands/ListIndexCommandDUnitTest.java | 38 +-
.../cli/commands/ListIndexCommandJUnitTest.java | 223 +++++++
.../internal/security/TestCommand.java | 3 +-
14 files changed, 1103 insertions(+), 914 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ClearDefinedIndexesCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ClearDefinedIndexesCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ClearDefinedIndexesCommand.java
new file mode 100644
index 0000000..d12f2c7
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ClearDefinedIndexesCommand.java
@@ -0,0 +1,40 @@
+/*
+ * 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.springframework.shell.core.annotation.CliCommand;
+
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.Result;
+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 ClearDefinedIndexesCommand implements GfshCommand {
+ @CliCommand(value = CliStrings.CLEAR_DEFINED_INDEXES, help = CliStrings.CLEAR_DEFINED__HELP)
+ @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
+ @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+ operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.QUERY)
+ // TODO : Add optionContext for indexName
+ public Result clearDefinedIndexes() {
+ IndexDefinition.indexDefinitions.clear();
+ InfoResultData infoResult = ResultBuilder.createInfoResultData();
+ infoResult.addLine(CliStrings.CLEAR_DEFINED_INDEX__SUCCESS__MSG);
+ return ResultBuilder.buildResult(infoResult);
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateDefinedIndexesCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateDefinedIndexesCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateDefinedIndexesCommand.java
new file mode 100644
index 0000000..3487279
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateDefinedIndexesCommand.java
@@ -0,0 +1,155 @@
+/*
+ * 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.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.CacheFactory;
+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.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.CreateDefinedIndexesFunction;
+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.configuration.domain.XmlEntity;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class CreateDefinedIndexesCommand implements GfshCommand {
+ private static final CreateDefinedIndexesFunction createDefinedIndexesFunction =
+ new CreateDefinedIndexesFunction();
+
+ @CliCommand(value = CliStrings.CREATE_DEFINED_INDEXES, help = CliStrings.CREATE_DEFINED__HELP)
+ @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
+ @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+ operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.QUERY)
+ // TODO : Add optionContext for indexName
+ public Result createDefinedIndexes(
+
+ @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
+ optionContext = ConverterHint.MEMBERIDNAME,
+ help = CliStrings.CREATE_DEFINED_INDEXES__MEMBER__HELP) final String[] memberNameOrID,
+
+ @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+ optionContext = ConverterHint.MEMBERGROUP,
+ help = CliStrings.CREATE_DEFINED_INDEXES__GROUP__HELP) final String[] group) {
+
+ Result result;
+ AtomicReference xmlEntity = new AtomicReference<>();
+
+ if (IndexDefinition.indexDefinitions.isEmpty()) {
+ final InfoResultData infoResult = ResultBuilder.createInfoResultData();
+ infoResult.addLine(CliStrings.DEFINE_INDEX__FAILURE__MSG);
+ return ResultBuilder.buildResult(infoResult);
+ }
+
+ try {
+ final Set targetMembers = CliUtil.findMembers(group, memberNameOrID);
+
+ if (targetMembers.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+ }
+
+ // TODO PSR: is this safe to remove?
+ CacheFactory.getAnyInstance();
+ final ResultCollector, ?> rc = CliUtil.executeFunction(createDefinedIndexesFunction,
+ IndexDefinition.indexDefinitions, targetMembers);
+
+ final List funcResults = (List) rc.getResult();
+ final Set successfulMembers = new TreeSet<>();
+ final Map> indexOpFailMap = new HashMap<>();
+
+ for (final Object funcResult : funcResults) {
+ if (funcResult instanceof CliFunctionResult) {
+ final CliFunctionResult cliFunctionResult = (CliFunctionResult) funcResult;
+
+ if (cliFunctionResult.isSuccessful()) {
+ successfulMembers.add(cliFunctionResult.getMemberIdOrName());
+
+ if (xmlEntity.get() == null) {
+ xmlEntity.set(cliFunctionResult.getXmlEntity());
+ }
+ } else {
+ final String exceptionMessage = cliFunctionResult.getMessage();
+ Set failedMembers = indexOpFailMap.get(exceptionMessage);
+
+ if (failedMembers == null) {
+ failedMembers = new TreeSet<>();
+ }
+ failedMembers.add(cliFunctionResult.getMemberIdOrName());
+ indexOpFailMap.put(exceptionMessage, failedMembers);
+ }
+ }
+ }
+
+ if (!successfulMembers.isEmpty()) {
+ final InfoResultData infoResult = ResultBuilder.createInfoResultData();
+ infoResult.addLine(CliStrings.CREATE_DEFINED_INDEXES__SUCCESS__MSG);
+
+ int num = 0;
+
+ for (final String memberId : successfulMembers) {
+ ++num;
+ infoResult.addLine(CliStrings
+ .format(CliStrings.CREATE_DEFINED_INDEXES__NUMBER__AND__MEMBER, num, memberId));
+ }
+ result = ResultBuilder.buildResult(infoResult);
+
+ } else {
+ // Group members by the exception thrown.
+ final ErrorResultData erd = ResultBuilder.createErrorResultData();
+
+ final Set exceptionMessages = indexOpFailMap.keySet();
+
+ for (final String exceptionMessage : exceptionMessages) {
+ erd.addLine(exceptionMessage);
+ erd.addLine(CliStrings.CREATE_INDEX__EXCEPTION__OCCURRED__ON);
+ final Set memberIds = indexOpFailMap.get(exceptionMessage);
+
+ int num = 0;
+ for (final String memberId : memberIds) {
+ ++num;
+ erd.addLine(CliStrings.format(CliStrings.CREATE_DEFINED_INDEXES__NUMBER__AND__MEMBER,
+ num, memberId));
+ }
+ }
+ result = ResultBuilder.buildResult(erd);
+ }
+ } catch (Exception e) {
+ result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+ }
+
+ if (xmlEntity.get() != null) {
+ persistClusterConfiguration(result,
+ () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), group));
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java
new file mode 100644
index 0000000..5bae92d
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateIndexCommand.java
@@ -0,0 +1,197 @@
+/*
+ * 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.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.lang.StringUtils;
+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.IndexInfo;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.CreateIndexFunction;
+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.configuration.domain.XmlEntity;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class CreateIndexCommand implements GfshCommand {
+ private static final CreateIndexFunction createIndexFunction = new CreateIndexFunction();
+
+ @CliCommand(value = CliStrings.CREATE_INDEX, help = CliStrings.CREATE_INDEX__HELP)
+ @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
+ // TODO : Add optionContext for indexName
+ @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+ operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.QUERY)
+ public Result createIndex(@CliOption(key = CliStrings.CREATE_INDEX__NAME, mandatory = true,
+ help = CliStrings.CREATE_INDEX__NAME__HELP) final String indexName,
+
+ @CliOption(key = CliStrings.CREATE_INDEX__EXPRESSION, mandatory = true,
+ help = CliStrings.CREATE_INDEX__EXPRESSION__HELP) final String indexedExpression,
+
+ @CliOption(key = CliStrings.CREATE_INDEX__REGION, mandatory = true,
+ optionContext = ConverterHint.REGION_PATH,
+ help = CliStrings.CREATE_INDEX__REGION__HELP) String regionPath,
+
+ @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
+ optionContext = ConverterHint.MEMBERIDNAME,
+ help = CliStrings.CREATE_INDEX__MEMBER__HELP) final String[] memberNameOrID,
+
+ @CliOption(key = CliStrings.CREATE_INDEX__TYPE, unspecifiedDefaultValue = "range",
+ optionContext = ConverterHint.INDEX_TYPE,
+ help = CliStrings.CREATE_INDEX__TYPE__HELP) final String indexType,
+
+ @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+ optionContext = ConverterHint.MEMBERGROUP,
+ help = CliStrings.CREATE_INDEX__GROUP__HELP) final String[] group) {
+
+ Result result;
+ AtomicReference xmlEntity = new AtomicReference<>();
+
+ try {
+ // TODO PSR: Is this safe to remove?
+ CacheFactory.getAnyInstance();
+ int idxType;
+
+ // Index type check
+ if ("range".equalsIgnoreCase(indexType)) {
+ idxType = IndexInfo.RANGE_INDEX;
+ } else if ("hash".equalsIgnoreCase(indexType)) {
+ idxType = IndexInfo.HASH_INDEX;
+ } else if ("key".equalsIgnoreCase(indexType)) {
+ idxType = IndexInfo.KEY_INDEX;
+ } else {
+ return ResultBuilder
+ .createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__INDEX__TYPE__MESSAGE);
+ }
+
+ if (indexName == null || indexName.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__INDEX__NAME);
+ }
+
+ if (indexedExpression == null || indexedExpression.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__EXPRESSION);
+ }
+
+ if (StringUtils.isBlank(regionPath) || regionPath.equals(Region.SEPARATOR)) {
+ return ResultBuilder.createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__REGIONPATH);
+ }
+
+ if (!regionPath.startsWith(Region.SEPARATOR)) {
+ regionPath = Region.SEPARATOR + regionPath;
+ }
+
+ IndexInfo indexInfo = new IndexInfo(indexName, indexedExpression, regionPath, idxType);
+ final Set targetMembers = CliUtil.findMembers(group, memberNameOrID);
+
+ if (targetMembers.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+ }
+
+ final ResultCollector, ?> rc =
+ CliUtil.executeFunction(createIndexFunction, indexInfo, targetMembers);
+
+ final List funcResults = (List) rc.getResult();
+ final Set successfulMembers = new TreeSet<>();
+ final Map> indexOpFailMap = new HashMap<>();
+
+ for (final Object funcResult : funcResults) {
+ if (funcResult instanceof CliFunctionResult) {
+ final CliFunctionResult cliFunctionResult = (CliFunctionResult) funcResult;
+
+ if (cliFunctionResult.isSuccessful()) {
+ successfulMembers.add(cliFunctionResult.getMemberIdOrName());
+
+ if (xmlEntity.get() == null) {
+ xmlEntity.set(cliFunctionResult.getXmlEntity());
+ }
+ } else {
+ final String exceptionMessage = cliFunctionResult.getMessage();
+ Set failedMembers = indexOpFailMap.get(exceptionMessage);
+
+ if (failedMembers == null) {
+ failedMembers = new TreeSet<>();
+ }
+ failedMembers.add(cliFunctionResult.getMemberIdOrName());
+ indexOpFailMap.put(exceptionMessage, failedMembers);
+ }
+ }
+ }
+
+ if (!successfulMembers.isEmpty()) {
+ final InfoResultData infoResult = ResultBuilder.createInfoResultData();
+ infoResult.addLine(CliStrings.CREATE_INDEX__SUCCESS__MSG);
+ infoResult.addLine(CliStrings.format(CliStrings.CREATE_INDEX__NAME__MSG, indexName));
+ infoResult.addLine(
+ CliStrings.format(CliStrings.CREATE_INDEX__EXPRESSION__MSG, indexedExpression));
+ infoResult.addLine(CliStrings.format(CliStrings.CREATE_INDEX__REGIONPATH__MSG, regionPath));
+ infoResult.addLine(CliStrings.CREATE_INDEX__MEMBER__MSG);
+
+ int num = 0;
+
+ for (final String memberId : successfulMembers) {
+ ++num;
+ infoResult.addLine(
+ CliStrings.format(CliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, num, memberId));
+ }
+ result = ResultBuilder.buildResult(infoResult);
+
+ } else {
+ // Group members by the exception thrown.
+ final ErrorResultData erd = ResultBuilder.createErrorResultData();
+ erd.addLine(CliStrings.format(CliStrings.CREATE_INDEX__FAILURE__MSG, indexName));
+ final Set exceptionMessages = indexOpFailMap.keySet();
+
+ for (final String exceptionMessage : exceptionMessages) {
+ erd.addLine(exceptionMessage);
+ erd.addLine(CliStrings.CREATE_INDEX__EXCEPTION__OCCURRED__ON);
+ final Set memberIds = indexOpFailMap.get(exceptionMessage);
+ int num = 0;
+ for (final String memberId : memberIds) {
+ ++num;
+ erd.addLine(
+ CliStrings.format(CliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, num, memberId));
+ }
+ }
+ result = ResultBuilder.buildResult(erd);
+ }
+ } catch (Exception e) {
+ result = ResultBuilder.createGemFireErrorResult(e.getMessage());
+ }
+ if (xmlEntity.get() != null) {
+ persistClusterConfiguration(result,
+ () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), group));
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DefineIndexCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DefineIndexCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DefineIndexCommand.java
new file mode 100644
index 0000000..1102cd8
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DefineIndexCommand.java
@@ -0,0 +1,95 @@
+/*
+ * 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.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.internal.lang.StringUtils;
+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.domain.IndexInfo;
+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 DefineIndexCommand implements GfshCommand {
+ @CliCommand(value = CliStrings.DEFINE_INDEX, help = CliStrings.DEFINE_INDEX__HELP)
+ @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
+ // TODO : Add optionContext for indexName
+ @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+ operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.QUERY)
+ public Result defineIndex(
+ @CliOption(key = CliStrings.DEFINE_INDEX_NAME, mandatory = true,
+ help = CliStrings.DEFINE_INDEX__HELP) final String indexName,
+ @CliOption(key = CliStrings.DEFINE_INDEX__EXPRESSION, mandatory = true,
+ help = CliStrings.DEFINE_INDEX__EXPRESSION__HELP) final String indexedExpression,
+ @CliOption(key = CliStrings.DEFINE_INDEX__REGION, mandatory = true,
+ optionContext = ConverterHint.REGION_PATH,
+ help = CliStrings.DEFINE_INDEX__REGION__HELP) String regionPath,
+ @CliOption(key = CliStrings.DEFINE_INDEX__TYPE, unspecifiedDefaultValue = "range",
+ optionContext = ConverterHint.INDEX_TYPE,
+ help = CliStrings.DEFINE_INDEX__TYPE__HELP) final String indexType) {
+
+ Result result;
+ int idxType;
+
+ // Index type check
+ if ("range".equalsIgnoreCase(indexType)) {
+ idxType = IndexInfo.RANGE_INDEX;
+ } else if ("hash".equalsIgnoreCase(indexType)) {
+ idxType = IndexInfo.HASH_INDEX;
+ } else if ("key".equalsIgnoreCase(indexType)) {
+ idxType = IndexInfo.KEY_INDEX;
+ } else {
+ return ResultBuilder
+ .createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__INDEX__TYPE__MESSAGE);
+ }
+
+ if (indexName == null || indexName.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__INDEX__NAME);
+ }
+
+ if (indexedExpression == null || indexedExpression.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__EXPRESSION);
+ }
+
+ if (StringUtils.isBlank(regionPath) || regionPath.equals(Region.SEPARATOR)) {
+ return ResultBuilder.createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__REGIONPATH);
+ }
+
+ if (!regionPath.startsWith(Region.SEPARATOR)) {
+ regionPath = Region.SEPARATOR + regionPath;
+ }
+
+ IndexInfo indexInfo = new IndexInfo(indexName, indexedExpression, regionPath, idxType);
+ IndexDefinition.indexDefinitions.add(indexInfo);
+
+ final InfoResultData infoResult = ResultBuilder.createInfoResultData();
+ infoResult.addLine(CliStrings.DEFINE_INDEX__SUCCESS__MSG);
+ infoResult.addLine(CliStrings.format(CliStrings.DEFINE_INDEX__NAME__MSG, indexName));
+ infoResult
+ .addLine(CliStrings.format(CliStrings.DEFINE_INDEX__EXPRESSION__MSG, indexedExpression));
+ infoResult.addLine(CliStrings.format(CliStrings.DEFINE_INDEX__REGIONPATH__MSG, regionPath));
+ result = ResultBuilder.buildResult(infoResult);
+
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyIndexCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyIndexCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyIndexCommand.java
new file mode 100644
index 0000000..c9f2b64
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyIndexCommand.java
@@ -0,0 +1,174 @@
+/*
+ * 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.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.lang.StringUtils;
+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.IndexInfo;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.DestroyIndexFunction;
+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.configuration.domain.XmlEntity;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class DestroyIndexCommand implements GfshCommand {
+ private static final DestroyIndexFunction destroyIndexFunction = new DestroyIndexFunction();
+
+ @CliCommand(value = CliStrings.DESTROY_INDEX, help = CliStrings.DESTROY_INDEX__HELP)
+ @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
+ @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+ operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.QUERY)
+ public Result destroyIndex(
+ @CliOption(key = CliStrings.DESTROY_INDEX__NAME, unspecifiedDefaultValue = "",
+ help = CliStrings.DESTROY_INDEX__NAME__HELP) final String indexName,
+
+ @CliOption(key = CliStrings.DESTROY_INDEX__REGION, optionContext = ConverterHint.REGION_PATH,
+ help = CliStrings.DESTROY_INDEX__REGION__HELP) final String regionPath,
+
+ @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
+ optionContext = ConverterHint.MEMBERIDNAME,
+ help = CliStrings.DESTROY_INDEX__MEMBER__HELP) final String[] memberNameOrID,
+
+ @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+ optionContext = ConverterHint.MEMBERGROUP,
+ help = CliStrings.DESTROY_INDEX__GROUP__HELP) final String[] group) {
+
+ Result result;
+
+ if (StringUtils.isBlank(indexName) && StringUtils.isBlank(regionPath)
+ && ArrayUtils.isEmpty(group) && ArrayUtils.isEmpty(memberNameOrID)) {
+ return ResultBuilder.createUserErrorResult(
+ CliStrings.format(CliStrings.PROVIDE_ATLEAST_ONE_OPTION, CliStrings.DESTROY_INDEX));
+ }
+
+ final Cache cache = CacheFactory.getAnyInstance();
+ String regionName = null;
+ if (regionPath != null) {
+ regionName = regionPath.startsWith("/") ? regionPath.substring(1) : regionPath;
+ }
+ IndexInfo indexInfo = new IndexInfo(indexName, regionName);
+ Set targetMembers = CliUtil.findMembers(group, memberNameOrID);
+
+ if (targetMembers.isEmpty()) {
+ return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+ }
+
+ ResultCollector rc = CliUtil.executeFunction(destroyIndexFunction, indexInfo, targetMembers);
+ List funcResults = (List) rc.getResult();
+
+ Set successfulMembers = new TreeSet<>();
+ Map> indexOpFailMap = new HashMap<>();
+
+ AtomicReference xmlEntity = new AtomicReference<>();
+ for (Object funcResult : funcResults) {
+ if (!(funcResult instanceof CliFunctionResult)) {
+ continue;
+ }
+ CliFunctionResult cliFunctionResult = (CliFunctionResult) funcResult;
+
+ if (cliFunctionResult.isSuccessful()) {
+ successfulMembers.add(cliFunctionResult.getMemberIdOrName());
+ if (xmlEntity.get() == null) {
+ xmlEntity.set(cliFunctionResult.getXmlEntity());
+ }
+ } else {
+ String exceptionMessage = cliFunctionResult.getMessage();
+ Set failedMembers = indexOpFailMap.get(exceptionMessage);
+
+ if (failedMembers == null) {
+ failedMembers = new TreeSet<>();
+ }
+ failedMembers.add(cliFunctionResult.getMemberIdOrName());
+ indexOpFailMap.put(exceptionMessage, failedMembers);
+ }
+ }
+ if (!successfulMembers.isEmpty()) {
+ InfoResultData infoResult = ResultBuilder.createInfoResultData();
+ if (StringUtils.isNotBlank(indexName)) {
+ if (StringUtils.isNotBlank(regionPath)) {
+ infoResult.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__ON__REGION__SUCCESS__MSG,
+ indexName, regionPath));
+ } else {
+ infoResult.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__SUCCESS__MSG, indexName));
+ }
+ } else {
+ if (StringUtils.isNotBlank(regionPath)) {
+ infoResult.addLine(CliStrings
+ .format(CliStrings.DESTROY_INDEX__ON__REGION__ONLY__SUCCESS__MSG, regionPath));
+ } else {
+ infoResult.addLine(CliStrings.DESTROY_INDEX__ON__MEMBERS__ONLY__SUCCESS__MSG);
+ }
+ }
+ int num = 0;
+ for (String memberId : successfulMembers) {
+ infoResult.addLine(CliStrings.format(
+ CliStrings.format(CliStrings.DESTROY_INDEX__NUMBER__AND__MEMBER, ++num, memberId)));
+ }
+ result = ResultBuilder.buildResult(infoResult);
+ } else {
+ ErrorResultData erd = ResultBuilder.createErrorResultData();
+ if (StringUtils.isNotBlank(indexName)) {
+ erd.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__FAILURE__MSG, indexName));
+ } else {
+ erd.addLine("Indexes could not be destroyed for following reasons");
+ }
+
+ Set exceptionMessages = indexOpFailMap.keySet();
+
+ for (String exceptionMessage : exceptionMessages) {
+ erd.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__REASON_MESSAGE, exceptionMessage));
+ erd.addLine(CliStrings.DESTROY_INDEX__EXCEPTION__OCCURRED__ON);
+
+ Set memberIds = indexOpFailMap.get(exceptionMessage);
+ int num = 0;
+
+ for (String memberId : memberIds) {
+ erd.addLine(CliStrings.format(
+ CliStrings.format(CliStrings.DESTROY_INDEX__NUMBER__AND__MEMBER, ++num, memberId)));
+ }
+ erd.addLine("");
+ }
+ result = ResultBuilder.buildResult(erd);
+ }
+ if (xmlEntity.get() != null) {
+ persistClusterConfiguration(result,
+ () -> getSharedConfiguration().deleteXmlEntity(xmlEntity.get(), group));
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexCommands.java
deleted file mode 100644
index 4734b4c..0000000
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexCommands.java
+++ /dev/null
@@ -1,668 +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.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.commons.lang.ArrayUtils;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
-
-import org.apache.geode.SystemFailure;
-import org.apache.geode.cache.Cache;
-import org.apache.geode.cache.CacheFactory;
-import org.apache.geode.cache.Region;
-import org.apache.geode.cache.execute.Execution;
-import org.apache.geode.cache.execute.FunctionInvocationTargetException;
-import org.apache.geode.cache.execute.ResultCollector;
-import org.apache.geode.distributed.DistributedMember;
-import org.apache.geode.internal.cache.execute.AbstractExecution;
-import org.apache.geode.internal.lang.StringUtils;
-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.IndexDetails;
-import org.apache.geode.management.internal.cli.domain.IndexDetails.IndexStatisticsDetails;
-import org.apache.geode.management.internal.cli.domain.IndexInfo;
-import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
-import org.apache.geode.management.internal.cli.functions.CreateDefinedIndexesFunction;
-import org.apache.geode.management.internal.cli.functions.CreateIndexFunction;
-import org.apache.geode.management.internal.cli.functions.DestroyIndexFunction;
-import org.apache.geode.management.internal.cli.functions.ListIndexFunction;
-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.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.apache.geode.security.ResourcePermission.Target;
-
-/**
- * The IndexCommands class encapsulates all GemFire shell (Gfsh) commands related to indexes defined
- * in GemFire.
- *
- * @see GfshCommand
- * @see org.apache.geode.management.internal.cli.domain.IndexDetails
- * @see org.apache.geode.management.internal.cli.functions.ListIndexFunction
- * @since GemFire 7.0
- */
-@SuppressWarnings("unused")
-public class IndexCommands implements GfshCommand {
-
- private static final CreateIndexFunction createIndexFunction = new CreateIndexFunction();
- private static final DestroyIndexFunction destroyIndexFunction = new DestroyIndexFunction();
- private static final CreateDefinedIndexesFunction createDefinedIndexesFunction =
- new CreateDefinedIndexesFunction();
- private static final Set indexDefinitions =
- Collections.synchronizedSet(new HashSet());
-
- @CliCommand(value = CliStrings.LIST_INDEX, help = CliStrings.LIST_INDEX__HELP)
- @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
- @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ, target = Target.QUERY)
- public Result listIndex(@CliOption(key = CliStrings.LIST_INDEX__STATS,
- specifiedDefaultValue = "true", unspecifiedDefaultValue = "false",
- help = CliStrings.LIST_INDEX__STATS__HELP) final boolean showStats) {
- try {
- return toTabularResult(getIndexListing(), showStats);
- } catch (FunctionInvocationTargetException ignore) {
- return ResultBuilder.createGemFireErrorResult(
- CliStrings.format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN, CliStrings.LIST_INDEX));
- } catch (VirtualMachineError e) {
- SystemFailure.initiateFailure(e);
- throw e;
- } catch (Throwable t) {
- SystemFailure.checkFailure();
- getCache().getLogger().error(t);
- return ResultBuilder.createGemFireErrorResult(
- String.format(CliStrings.LIST_INDEX__ERROR_MESSAGE, toString(t, isDebugging())));
- }
- }
-
- @SuppressWarnings("unchecked")
- protected List getIndexListing() {
- final Execution functionExecutor = getMembersFunctionExecutor(getMembers(getCache()));
-
- if (functionExecutor instanceof AbstractExecution) {
- ((AbstractExecution) functionExecutor).setIgnoreDepartedMembers(true);
- }
-
- final ResultCollector, ?> resultsCollector =
- functionExecutor.execute(new ListIndexFunction());
-
- final List> results = (List>) resultsCollector.getResult();
- final List indexDetailsList = new ArrayList<>(results.size());
-
- for (Object result : results) {
- if (result instanceof Set) { // ignore FunctionInvocationTargetExceptions and other Exceptions
- indexDetailsList.addAll((Set) result);
- }
- }
-
- Collections.sort(indexDetailsList);
-
- return indexDetailsList;
- }
-
- protected Result toTabularResult(final List indexDetailsList,
- final boolean showStats) {
- if (!indexDetailsList.isEmpty()) {
- final TabularResultData indexData = ResultBuilder.createTabularResultData();
-
- for (final IndexDetails indexDetails : indexDetailsList) {
- indexData.accumulate("Member Name",
- StringUtils.defaultString(indexDetails.getMemberName()));
- indexData.accumulate("Member ID", indexDetails.getMemberId());
- indexData.accumulate("Region Path", indexDetails.getRegionPath());
- indexData.accumulate("Name", indexDetails.getIndexName());
- indexData.accumulate("Type", StringUtils.defaultString(indexDetails.getIndexType()));
- indexData.accumulate("Indexed Expression", indexDetails.getIndexedExpression());
- indexData.accumulate("From Clause", indexDetails.getFromClause());
-
- if (showStats) {
- final IndexStatisticsDetailsAdapter adapter =
- new IndexStatisticsDetailsAdapter(indexDetails.getIndexStatisticsDetails());
-
- indexData.accumulate("Uses", adapter.getTotalUses());
- indexData.accumulate("Updates", adapter.getNumberOfUpdates());
- indexData.accumulate("Update Time", adapter.getTotalUpdateTime());
- indexData.accumulate("Keys", adapter.getNumberOfKeys());
- indexData.accumulate("Values", adapter.getNumberOfValues());
- }
- }
-
- return ResultBuilder.buildResult(indexData);
- } else {
- return ResultBuilder.createInfoResult(CliStrings.LIST_INDEX__INDEXES_NOT_FOUND_MESSAGE);
- }
- }
-
- @CliCommand(value = CliStrings.CREATE_INDEX, help = CliStrings.CREATE_INDEX__HELP)
- @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
- // TODO : Add optionContext for indexName
- @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE,
- target = Target.QUERY)
- public Result createIndex(@CliOption(key = CliStrings.CREATE_INDEX__NAME, mandatory = true,
- help = CliStrings.CREATE_INDEX__NAME__HELP) final String indexName,
-
- @CliOption(key = CliStrings.CREATE_INDEX__EXPRESSION, mandatory = true,
- help = CliStrings.CREATE_INDEX__EXPRESSION__HELP) final String indexedExpression,
-
- @CliOption(key = CliStrings.CREATE_INDEX__REGION, mandatory = true,
- optionContext = ConverterHint.REGION_PATH,
- help = CliStrings.CREATE_INDEX__REGION__HELP) String regionPath,
-
- @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
- optionContext = ConverterHint.MEMBERIDNAME,
- help = CliStrings.CREATE_INDEX__MEMBER__HELP) final String[] memberNameOrID,
-
- @CliOption(key = CliStrings.CREATE_INDEX__TYPE, unspecifiedDefaultValue = "range",
- optionContext = ConverterHint.INDEX_TYPE,
- help = CliStrings.CREATE_INDEX__TYPE__HELP) final String indexType,
-
- @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
- optionContext = ConverterHint.MEMBERGROUP,
- help = CliStrings.CREATE_INDEX__GROUP__HELP) final String[] group) {
-
- Result result;
- AtomicReference xmlEntity = new AtomicReference<>();
-
- try {
- final Cache cache = CacheFactory.getAnyInstance();
-
- int idxType;
-
- // Index type check
- if ("range".equalsIgnoreCase(indexType)) {
- idxType = IndexInfo.RANGE_INDEX;
- } else if ("hash".equalsIgnoreCase(indexType)) {
- idxType = IndexInfo.HASH_INDEX;
- } else if ("key".equalsIgnoreCase(indexType)) {
- idxType = IndexInfo.KEY_INDEX;
- } else {
- return ResultBuilder
- .createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__INDEX__TYPE__MESSAGE);
- }
-
- if (indexName == null || indexName.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__INDEX__NAME);
- }
-
- if (indexedExpression == null || indexedExpression.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__EXPRESSION);
- }
-
- if (StringUtils.isBlank(regionPath) || regionPath.equals(Region.SEPARATOR)) {
- return ResultBuilder.createUserErrorResult(CliStrings.CREATE_INDEX__INVALID__REGIONPATH);
- }
-
- if (!regionPath.startsWith(Region.SEPARATOR)) {
- regionPath = Region.SEPARATOR + regionPath;
- }
-
- IndexInfo indexInfo = new IndexInfo(indexName, indexedExpression, regionPath, idxType);
-
- final Set targetMembers = CliUtil.findMembers(group, memberNameOrID);
-
- if (targetMembers.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
- }
-
- final ResultCollector, ?> rc =
- CliUtil.executeFunction(createIndexFunction, indexInfo, targetMembers);
-
- final List funcResults = (List) rc.getResult();
- final Set successfulMembers = new TreeSet<>();
- final Map> indexOpFailMap = new HashMap<>();
-
- for (final Object funcResult : funcResults) {
- if (funcResult instanceof CliFunctionResult) {
- final CliFunctionResult cliFunctionResult = (CliFunctionResult) funcResult;
-
- if (cliFunctionResult.isSuccessful()) {
- successfulMembers.add(cliFunctionResult.getMemberIdOrName());
-
- if (xmlEntity.get() == null) {
- xmlEntity.set(cliFunctionResult.getXmlEntity());
- }
- } else {
- final String exceptionMessage = cliFunctionResult.getMessage();
- Set failedMembers = indexOpFailMap.get(exceptionMessage);
-
- if (failedMembers == null) {
- failedMembers = new TreeSet<>();
- }
- failedMembers.add(cliFunctionResult.getMemberIdOrName());
- indexOpFailMap.put(exceptionMessage, failedMembers);
- }
- }
- }
-
- if (!successfulMembers.isEmpty()) {
-
- final InfoResultData infoResult = ResultBuilder.createInfoResultData();
- infoResult.addLine(CliStrings.CREATE_INDEX__SUCCESS__MSG);
- infoResult.addLine(CliStrings.format(CliStrings.CREATE_INDEX__NAME__MSG, indexName));
- infoResult.addLine(
- CliStrings.format(CliStrings.CREATE_INDEX__EXPRESSION__MSG, indexedExpression));
- infoResult.addLine(CliStrings.format(CliStrings.CREATE_INDEX__REGIONPATH__MSG, regionPath));
- infoResult.addLine(CliStrings.CREATE_INDEX__MEMBER__MSG);
-
- int num = 0;
-
- for (final String memberId : successfulMembers) {
- ++num;
- infoResult.addLine(
- CliStrings.format(CliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, num, memberId));
- }
- result = ResultBuilder.buildResult(infoResult);
-
- } else {
- // Group members by the exception thrown.
- final ErrorResultData erd = ResultBuilder.createErrorResultData();
- erd.addLine(CliStrings.format(CliStrings.CREATE_INDEX__FAILURE__MSG, indexName));
-
- final Set exceptionMessages = indexOpFailMap.keySet();
-
- for (final String exceptionMessage : exceptionMessages) {
- erd.addLine(exceptionMessage);
- erd.addLine(CliStrings.CREATE_INDEX__EXCEPTION__OCCURRED__ON);
- final Set memberIds = indexOpFailMap.get(exceptionMessage);
-
- int num = 0;
- for (final String memberId : memberIds) {
- ++num;
- erd.addLine(
- CliStrings.format(CliStrings.CREATE_INDEX__NUMBER__AND__MEMBER, num, memberId));
- }
- }
- result = ResultBuilder.buildResult(erd);
- }
- } catch (Exception e) {
- result = ResultBuilder.createGemFireErrorResult(e.getMessage());
- }
-
- if (xmlEntity.get() != null) {
- persistClusterConfiguration(result,
- () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), group));
- }
-
- return result;
- }
-
- @CliCommand(value = CliStrings.DESTROY_INDEX, help = CliStrings.DESTROY_INDEX__HELP)
- @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
- @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE,
- target = Target.QUERY)
- public Result destroyIndex(
- @CliOption(key = CliStrings.DESTROY_INDEX__NAME, unspecifiedDefaultValue = "",
- help = CliStrings.DESTROY_INDEX__NAME__HELP) final String indexName,
-
- @CliOption(key = CliStrings.DESTROY_INDEX__REGION, optionContext = ConverterHint.REGION_PATH,
- help = CliStrings.DESTROY_INDEX__REGION__HELP) final String regionPath,
-
- @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
- optionContext = ConverterHint.MEMBERIDNAME,
- help = CliStrings.DESTROY_INDEX__MEMBER__HELP) final String[] memberNameOrID,
-
- @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
- optionContext = ConverterHint.MEMBERGROUP,
- help = CliStrings.DESTROY_INDEX__GROUP__HELP) final String[] group) {
-
- Result result;
-
- if (StringUtils.isBlank(indexName) && StringUtils.isBlank(regionPath)
- && ArrayUtils.isEmpty(group) && ArrayUtils.isEmpty(memberNameOrID)) {
- return ResultBuilder.createUserErrorResult(
- CliStrings.format(CliStrings.PROVIDE_ATLEAST_ONE_OPTION, CliStrings.DESTROY_INDEX));
- }
-
- final Cache cache = CacheFactory.getAnyInstance();
- String regionName = null;
- if (regionPath != null) {
- regionName = regionPath.startsWith("/") ? regionPath.substring(1) : regionPath;
- }
- IndexInfo indexInfo = new IndexInfo(indexName, regionName);
- Set targetMembers = CliUtil.findMembers(group, memberNameOrID);
-
- if (targetMembers.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
- }
-
- ResultCollector rc = CliUtil.executeFunction(destroyIndexFunction, indexInfo, targetMembers);
- List funcResults = (List) rc.getResult();
-
- Set successfulMembers = new TreeSet<>();
- Map> indexOpFailMap = new HashMap<>();
-
- AtomicReference xmlEntity = new AtomicReference<>();
- for (Object funcResult : funcResults) {
- if (!(funcResult instanceof CliFunctionResult)) {
- continue;
- }
-
- CliFunctionResult cliFunctionResult = (CliFunctionResult) funcResult;
-
- if (cliFunctionResult.isSuccessful()) {
- successfulMembers.add(cliFunctionResult.getMemberIdOrName());
- if (xmlEntity.get() == null) {
- xmlEntity.set(cliFunctionResult.getXmlEntity());
- }
- } else {
- String exceptionMessage = cliFunctionResult.getMessage();
- Set failedMembers = indexOpFailMap.get(exceptionMessage);
-
- if (failedMembers == null) {
- failedMembers = new TreeSet<>();
- }
- failedMembers.add(cliFunctionResult.getMemberIdOrName());
- indexOpFailMap.put(exceptionMessage, failedMembers);
- }
- }
-
- if (!successfulMembers.isEmpty()) {
- InfoResultData infoResult = ResultBuilder.createInfoResultData();
-
- if (StringUtils.isNotBlank(indexName)) {
- if (StringUtils.isNotBlank(regionPath)) {
- infoResult.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__ON__REGION__SUCCESS__MSG,
- indexName, regionPath));
- } else {
- infoResult.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__SUCCESS__MSG, indexName));
- }
- } else {
- if (StringUtils.isNotBlank(regionPath)) {
- infoResult.addLine(CliStrings
- .format(CliStrings.DESTROY_INDEX__ON__REGION__ONLY__SUCCESS__MSG, regionPath));
- } else {
- infoResult.addLine(CliStrings.DESTROY_INDEX__ON__MEMBERS__ONLY__SUCCESS__MSG);
- }
- }
-
- int num = 0;
- for (String memberId : successfulMembers) {
- infoResult.addLine(CliStrings.format(
- CliStrings.format(CliStrings.DESTROY_INDEX__NUMBER__AND__MEMBER, ++num, memberId)));
- }
- result = ResultBuilder.buildResult(infoResult);
-
- } else {
-
- ErrorResultData erd = ResultBuilder.createErrorResultData();
- if (StringUtils.isNotBlank(indexName)) {
- erd.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__FAILURE__MSG, indexName));
- } else {
- erd.addLine("Indexes could not be destroyed for following reasons");
- }
-
- Set exceptionMessages = indexOpFailMap.keySet();
-
- for (String exceptionMessage : exceptionMessages) {
- erd.addLine(CliStrings.format(CliStrings.DESTROY_INDEX__REASON_MESSAGE, exceptionMessage));
- erd.addLine(CliStrings.DESTROY_INDEX__EXCEPTION__OCCURRED__ON);
-
- Set memberIds = indexOpFailMap.get(exceptionMessage);
- int num = 0;
-
- for (String memberId : memberIds) {
- erd.addLine(CliStrings.format(
- CliStrings.format(CliStrings.DESTROY_INDEX__NUMBER__AND__MEMBER, ++num, memberId)));
- }
- erd.addLine("");
- }
- result = ResultBuilder.buildResult(erd);
- }
- if (xmlEntity.get() != null) {
- persistClusterConfiguration(result,
- () -> getSharedConfiguration().deleteXmlEntity(xmlEntity.get(), group));
- }
-
- return result;
- }
-
- @CliCommand(value = CliStrings.DEFINE_INDEX, help = CliStrings.DEFINE_INDEX__HELP)
- @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
- // TODO : Add optionContext for indexName
- @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE,
- target = Target.QUERY)
- public Result defineIndex(@CliOption(key = CliStrings.DEFINE_INDEX_NAME, mandatory = true,
- help = CliStrings.DEFINE_INDEX__HELP) final String indexName,
-
- @CliOption(key = CliStrings.DEFINE_INDEX__EXPRESSION, mandatory = true,
- help = CliStrings.DEFINE_INDEX__EXPRESSION__HELP) final String indexedExpression,
-
- @CliOption(key = CliStrings.DEFINE_INDEX__REGION, mandatory = true,
- optionContext = ConverterHint.REGION_PATH,
- help = CliStrings.DEFINE_INDEX__REGION__HELP) String regionPath,
-
- @CliOption(key = CliStrings.DEFINE_INDEX__TYPE, unspecifiedDefaultValue = "range",
- optionContext = ConverterHint.INDEX_TYPE,
- help = CliStrings.DEFINE_INDEX__TYPE__HELP) final String indexType) {
-
- Result result;
- XmlEntity xmlEntity = null;
-
- int idxType;
-
- // Index type check
- if ("range".equalsIgnoreCase(indexType)) {
- idxType = IndexInfo.RANGE_INDEX;
- } else if ("hash".equalsIgnoreCase(indexType)) {
- idxType = IndexInfo.HASH_INDEX;
- } else if ("key".equalsIgnoreCase(indexType)) {
- idxType = IndexInfo.KEY_INDEX;
- } else {
- return ResultBuilder
- .createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__INDEX__TYPE__MESSAGE);
- }
-
- if (indexName == null || indexName.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__INDEX__NAME);
- }
-
- if (indexedExpression == null || indexedExpression.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__EXPRESSION);
- }
-
- if (StringUtils.isBlank(regionPath) || regionPath.equals(Region.SEPARATOR)) {
- return ResultBuilder.createUserErrorResult(CliStrings.DEFINE_INDEX__INVALID__REGIONPATH);
- }
-
- if (!regionPath.startsWith(Region.SEPARATOR)) {
- regionPath = Region.SEPARATOR + regionPath;
- }
-
- IndexInfo indexInfo = new IndexInfo(indexName, indexedExpression, regionPath, idxType);
- indexDefinitions.add(indexInfo);
-
- final InfoResultData infoResult = ResultBuilder.createInfoResultData();
- infoResult.addLine(CliStrings.DEFINE_INDEX__SUCCESS__MSG);
- infoResult.addLine(CliStrings.format(CliStrings.DEFINE_INDEX__NAME__MSG, indexName));
- infoResult
- .addLine(CliStrings.format(CliStrings.DEFINE_INDEX__EXPRESSION__MSG, indexedExpression));
- infoResult.addLine(CliStrings.format(CliStrings.DEFINE_INDEX__REGIONPATH__MSG, regionPath));
- result = ResultBuilder.buildResult(infoResult);
-
- return result;
- }
-
- @CliCommand(value = CliStrings.CREATE_DEFINED_INDEXES, help = CliStrings.CREATE_DEFINED__HELP)
- @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
- @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE,
- target = Target.QUERY)
- // TODO : Add optionContext for indexName
- public Result createDefinedIndexes(
-
- @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
- optionContext = ConverterHint.MEMBERIDNAME,
- help = CliStrings.CREATE_DEFINED_INDEXES__MEMBER__HELP) final String[] memberNameOrID,
-
- @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
- optionContext = ConverterHint.MEMBERGROUP,
- help = CliStrings.CREATE_DEFINED_INDEXES__GROUP__HELP) final String[] group) {
-
- Result result;
- AtomicReference xmlEntity = new AtomicReference<>();
-
- if (indexDefinitions.isEmpty()) {
- final InfoResultData infoResult = ResultBuilder.createInfoResultData();
- infoResult.addLine(CliStrings.DEFINE_INDEX__FAILURE__MSG);
- return ResultBuilder.buildResult(infoResult);
- }
-
- try {
- final Set targetMembers = CliUtil.findMembers(group, memberNameOrID);
-
- if (targetMembers.isEmpty()) {
- return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
- }
-
- final Cache cache = CacheFactory.getAnyInstance();
- final ResultCollector, ?> rc =
- CliUtil.executeFunction(createDefinedIndexesFunction, indexDefinitions, targetMembers);
-
- final List funcResults = (List) rc.getResult();
- final Set successfulMembers = new TreeSet<>();
- final Map> indexOpFailMap = new HashMap<>();
-
- for (final Object funcResult : funcResults) {
- if (funcResult instanceof CliFunctionResult) {
- final CliFunctionResult cliFunctionResult = (CliFunctionResult) funcResult;
-
- if (cliFunctionResult.isSuccessful()) {
- successfulMembers.add(cliFunctionResult.getMemberIdOrName());
-
- if (xmlEntity.get() == null) {
- xmlEntity.set(cliFunctionResult.getXmlEntity());
- }
- } else {
- final String exceptionMessage = cliFunctionResult.getMessage();
- Set failedMembers = indexOpFailMap.get(exceptionMessage);
-
- if (failedMembers == null) {
- failedMembers = new TreeSet<>();
- }
- failedMembers.add(cliFunctionResult.getMemberIdOrName());
- indexOpFailMap.put(exceptionMessage, failedMembers);
- }
- }
- }
-
- if (!successfulMembers.isEmpty()) {
- final InfoResultData infoResult = ResultBuilder.createInfoResultData();
- infoResult.addLine(CliStrings.CREATE_DEFINED_INDEXES__SUCCESS__MSG);
-
- int num = 0;
-
- for (final String memberId : successfulMembers) {
- ++num;
- infoResult.addLine(CliStrings
- .format(CliStrings.CREATE_DEFINED_INDEXES__NUMBER__AND__MEMBER, num, memberId));
- }
- result = ResultBuilder.buildResult(infoResult);
-
- } else {
- // Group members by the exception thrown.
- final ErrorResultData erd = ResultBuilder.createErrorResultData();
-
- final Set exceptionMessages = indexOpFailMap.keySet();
-
- for (final String exceptionMessage : exceptionMessages) {
- erd.addLine(exceptionMessage);
- erd.addLine(CliStrings.CREATE_INDEX__EXCEPTION__OCCURRED__ON);
- final Set memberIds = indexOpFailMap.get(exceptionMessage);
-
- int num = 0;
- for (final String memberId : memberIds) {
- ++num;
- erd.addLine(CliStrings.format(CliStrings.CREATE_DEFINED_INDEXES__NUMBER__AND__MEMBER,
- num, memberId));
- }
- }
- result = ResultBuilder.buildResult(erd);
- }
- } catch (Exception e) {
- result = ResultBuilder.createGemFireErrorResult(e.getMessage());
- }
-
- if (xmlEntity.get() != null) {
- persistClusterConfiguration(result,
- () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), group));
- }
- return result;
- }
-
- @CliCommand(value = CliStrings.CLEAR_DEFINED_INDEXES, help = CliStrings.CLEAR_DEFINED__HELP)
- @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
- @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE,
- target = Target.QUERY)
- // TODO : Add optionContext for indexName
- public Result clearDefinedIndexes() {
- indexDefinitions.clear();
- final InfoResultData infoResult = ResultBuilder.createInfoResultData();
- infoResult.addLine(CliStrings.CLEAR_DEFINED_INDEX__SUCCESS__MSG);
- return ResultBuilder.buildResult(infoResult);
- }
-
- protected static class IndexStatisticsDetailsAdapter {
-
- private final IndexStatisticsDetails indexStatisticsDetails;
-
- protected IndexStatisticsDetailsAdapter(final IndexStatisticsDetails indexStatisticsDetails) {
- this.indexStatisticsDetails = indexStatisticsDetails;
- }
-
- public IndexStatisticsDetails getIndexStatisticsDetails() {
- return indexStatisticsDetails;
- }
-
- public String getNumberOfKeys() {
- return getIndexStatisticsDetails() != null
- ? StringUtils.defaultString(getIndexStatisticsDetails().getNumberOfKeys()) : "";
- }
-
- public String getNumberOfUpdates() {
- return getIndexStatisticsDetails() != null
- ? StringUtils.defaultString(getIndexStatisticsDetails().getNumberOfUpdates()) : "";
- }
-
- public String getNumberOfValues() {
- return getIndexStatisticsDetails() != null
- ? StringUtils.defaultString(getIndexStatisticsDetails().getNumberOfValues()) : "";
- }
-
- public String getTotalUpdateTime() {
- return getIndexStatisticsDetails() != null
- ? StringUtils.defaultString(getIndexStatisticsDetails().getTotalUpdateTime()) : "";
- }
-
- public String getTotalUses() {
- return getIndexStatisticsDetails() != null
- ? StringUtils.defaultString(getIndexStatisticsDetails().getTotalUses()) : "";
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexDefinition.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexDefinition.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexDefinition.java
new file mode 100644
index 0000000..2cf9f83
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/IndexDefinition.java
@@ -0,0 +1,27 @@
+/*
+ * 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.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.geode.management.internal.cli.domain.IndexInfo;
+
+class IndexDefinition {
+ static final Set indexDefinitions =
+ Collections.synchronizedSet(new HashSet());
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListIndexCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListIndexCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListIndexCommand.java
new file mode 100644
index 0000000..847426c
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ListIndexCommand.java
@@ -0,0 +1,158 @@
+/*
+ * 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.Collections;
+import java.util.List;
+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.Execution;
+import org.apache.geode.cache.execute.FunctionInvocationTargetException;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.internal.cache.execute.AbstractExecution;
+import org.apache.geode.internal.lang.StringUtils;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.domain.IndexDetails;
+import org.apache.geode.management.internal.cli.domain.IndexDetails.IndexStatisticsDetails;
+import org.apache.geode.management.internal.cli.functions.ListIndexFunction;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+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 ListIndexCommand implements GfshCommand {
+ @CliCommand(value = CliStrings.LIST_INDEX, help = CliStrings.LIST_INDEX__HELP)
+ @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_REGION, CliStrings.TOPIC_GEODE_DATA})
+ @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+ operation = ResourcePermission.Operation.READ, target = ResourcePermission.Target.QUERY)
+ public Result listIndex(@CliOption(key = CliStrings.LIST_INDEX__STATS,
+ specifiedDefaultValue = "true", unspecifiedDefaultValue = "false",
+ help = CliStrings.LIST_INDEX__STATS__HELP) final boolean showStats) {
+ try {
+ return toTabularResult(getIndexListing(), showStats);
+ } catch (FunctionInvocationTargetException ignore) {
+ return ResultBuilder.createGemFireErrorResult(
+ CliStrings.format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN, CliStrings.LIST_INDEX));
+ } catch (VirtualMachineError e) {
+ SystemFailure.initiateFailure(e);
+ throw e;
+ } catch (Throwable t) {
+ SystemFailure.checkFailure();
+ getCache().getLogger().error(t);
+ return ResultBuilder.createGemFireErrorResult(
+ String.format(CliStrings.LIST_INDEX__ERROR_MESSAGE, toString(t, isDebugging())));
+ }
+ }
+
+ private Result toTabularResult(final List indexDetailsList,
+ final boolean showStats) {
+ if (!indexDetailsList.isEmpty()) {
+ final TabularResultData indexData = ResultBuilder.createTabularResultData();
+
+ for (final IndexDetails indexDetails : indexDetailsList) {
+ indexData.accumulate("Member Name",
+ StringUtils.defaultString(indexDetails.getMemberName()));
+ indexData.accumulate("Member ID", indexDetails.getMemberId());
+ indexData.accumulate("Region Path", indexDetails.getRegionPath());
+ indexData.accumulate("Name", indexDetails.getIndexName());
+ indexData.accumulate("Type", StringUtils.defaultString(indexDetails.getIndexType()));
+ indexData.accumulate("Indexed Expression", indexDetails.getIndexedExpression());
+ indexData.accumulate("From Clause", indexDetails.getFromClause());
+
+ if (showStats) {
+ final IndexStatisticsDetailsAdapter adapter =
+ new IndexStatisticsDetailsAdapter(indexDetails.getIndexStatisticsDetails());
+
+ indexData.accumulate("Uses", adapter.getTotalUses());
+ indexData.accumulate("Updates", adapter.getNumberOfUpdates());
+ indexData.accumulate("Update Time", adapter.getTotalUpdateTime());
+ indexData.accumulate("Keys", adapter.getNumberOfKeys());
+ indexData.accumulate("Values", adapter.getNumberOfValues());
+ }
+ }
+
+ return ResultBuilder.buildResult(indexData);
+ } else {
+ return ResultBuilder.createInfoResult(CliStrings.LIST_INDEX__INDEXES_NOT_FOUND_MESSAGE);
+ }
+ }
+
+ List getIndexListing() {
+ final Execution functionExecutor = getMembersFunctionExecutor(getMembers(getCache()));
+
+ if (functionExecutor instanceof AbstractExecution) {
+ ((AbstractExecution) functionExecutor).setIgnoreDepartedMembers(true);
+ }
+
+ final ResultCollector, ?> resultsCollector =
+ functionExecutor.execute(new ListIndexFunction());
+ final List> results = (List>) resultsCollector.getResult();
+ final List indexDetailsList = new ArrayList<>(results.size());
+
+ for (Object result : results) {
+ if (result instanceof Set) { // ignore FunctionInvocationTargetExceptions and other Exceptions
+ indexDetailsList.addAll((Set) result);
+ }
+ }
+ Collections.sort(indexDetailsList);
+ return indexDetailsList;
+ }
+
+ protected static class IndexStatisticsDetailsAdapter {
+
+ private final IndexStatisticsDetails indexStatisticsDetails;
+
+ protected IndexStatisticsDetailsAdapter(final IndexStatisticsDetails indexStatisticsDetails) {
+ this.indexStatisticsDetails = indexStatisticsDetails;
+ }
+
+ public IndexStatisticsDetails getIndexStatisticsDetails() {
+ return indexStatisticsDetails;
+ }
+
+ public String getNumberOfKeys() {
+ return getIndexStatisticsDetails() != null
+ ? StringUtils.defaultString(getIndexStatisticsDetails().getNumberOfKeys()) : "";
+ }
+
+ public String getNumberOfUpdates() {
+ return getIndexStatisticsDetails() != null
+ ? StringUtils.defaultString(getIndexStatisticsDetails().getNumberOfUpdates()) : "";
+ }
+
+ public String getNumberOfValues() {
+ return getIndexStatisticsDetails() != null
+ ? StringUtils.defaultString(getIndexStatisticsDetails().getNumberOfValues()) : "";
+ }
+
+ public String getTotalUpdateTime() {
+ return getIndexStatisticsDetails() != null
+ ? StringUtils.defaultString(getIndexStatisticsDetails().getTotalUpdateTime()) : "";
+ }
+
+ public String getTotalUses() {
+ return getIndexStatisticsDetails() != null
+ ? StringUtils.defaultString(getIndexStatisticsDetails().getTotalUses()) : "";
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/CreateDefinedIndexesFunction.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/CreateDefinedIndexesFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/CreateDefinedIndexesFunction.java
index 742840c..47cdb27 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/CreateDefinedIndexesFunction.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/CreateDefinedIndexesFunction.java
@@ -14,7 +14,6 @@
*/
package org.apache.geode.management.internal.cli.functions;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -38,7 +37,7 @@ public class CreateDefinedIndexesFunction extends FunctionAdapter implements Int
public void execute(FunctionContext context) {
String memberId = null;
List indexes = null;
- Cache cache = null;
+ Cache cache;
try {
cache = CacheFactory.getAnyInstance();
memberId = cache.getDistributedSystem().getDistributedMember().getId();
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/IndexCommandsController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/IndexCommandsController.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/IndexCommandsController.java
index 296156f..09d7f9a 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/IndexCommandsController.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/IndexCommandsController.java
@@ -14,9 +14,6 @@
*/
package org.apache.geode.management.internal.web.controllers;
-import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
-
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -24,11 +21,19 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
+
/**
* The IndexCommandsController class implements the REST API calls for the Gfsh Index commands.
*
*
- * @see org.apache.geode.management.internal.cli.commands.IndexCommands
+ * @see org.apache.geode.management.internal.cli.commands.ClearDefinedIndexesCommand
+ * @see org.apache.geode.management.internal.cli.commands.CreateDefinedIndexesCommand
+ * @see org.apache.geode.management.internal.cli.commands.CreateIndexCommand
+ * @see org.apache.geode.management.internal.cli.commands.DefineIndexCommand
+ * @see org.apache.geode.management.internal.cli.commands.DestroyIndexCommand
+ * @see org.apache.geode.management.internal.cli.commands.ListIndexCommand
* @see org.apache.geode.management.internal.cli.util.CommandStringBuilder
* @see org.apache.geode.management.internal.web.controllers.AbstractCommandsController
* @see org.springframework.stereotype.Controller
http://git-wip-us.apache.org/repos/asf/geode/blob/0dc67f0e/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/IndexCommandsJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/IndexCommandsJUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/IndexCommandsJUnitTest.java
deleted file mode 100644
index 0d1f340..0000000
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/IndexCommandsJUnitTest.java
+++ /dev/null
@@ -1,223 +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 static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.lib.concurrent.Synchroniser;
-import org.jmock.lib.legacy.ClassImposteriser;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import org.apache.geode.cache.execute.Execution;
-import org.apache.geode.cache.execute.FunctionInvocationTargetException;
-import org.apache.geode.cache.execute.ResultCollector;
-import org.apache.geode.distributed.DistributedMember;
-import org.apache.geode.internal.cache.InternalCache;
-import org.apache.geode.internal.cache.execute.AbstractExecution;
-import org.apache.geode.internal.util.CollectionUtils;
-import org.apache.geode.management.internal.cli.domain.IndexDetails;
-import org.apache.geode.management.internal.cli.functions.ListIndexFunction;
-import org.apache.geode.test.junit.categories.UnitTest;
-
-/**
- * The IndexCommandsJUnitTest class is a test suite of test cases testing the contract and
- * functionality of the IndexCommands class.
- *
- *
- * @see org.apache.geode.management.internal.cli.commands.IndexCommands
- * @see org.apache.geode.management.internal.cli.domain.IndexDetails
- * @see org.apache.geode.management.internal.cli.functions.ListIndexFunction
- * @see org.jmock.Expectations
- * @see org.jmock.Mockery
- * @see org.jmock.lib.legacy.ClassImposteriser
- * @see org.junit.Assert
- * @see org.junit.Test
- * @since GemFire 7.0
- */
-@Category(UnitTest.class)
-public class IndexCommandsJUnitTest {
-
- private Mockery mockContext;
-
- @Before
- public void setup() {
- mockContext = new Mockery() {
- {
- setImposteriser(ClassImposteriser.INSTANCE);
- setThreadingPolicy(new Synchroniser());
- }
- };
- }
-
- @After
- public void tearDown() {
- mockContext.assertIsSatisfied();
- mockContext = null;
- }
-
- private IndexCommands createIndexCommands(final InternalCache cache,
- final Execution functionExecutor) {
- return new TestIndexCommands(cache, functionExecutor);
- }
-
- private IndexDetails createIndexDetails(final String memberId, final String regionPath,
- final String indexName) {
- return new IndexDetails(memberId, regionPath, indexName);
- }
-
- @Test
- public void testGetIndexListing() {
- final InternalCache mockCache = mockContext.mock(InternalCache.class, "InternalCache");
-
- final AbstractExecution mockFunctionExecutor =
- mockContext.mock(AbstractExecution.class, "Function Executor");
-
- final ResultCollector mockResultCollector =
- mockContext.mock(ResultCollector.class, "ResultCollector");
-
- final IndexDetails indexDetails1 = createIndexDetails("memberOne", "/Employees", "empIdIdx");
- final IndexDetails indexDetails2 =
- createIndexDetails("memberOne", "/Employees", "empLastNameIdx");
- final IndexDetails indexDetails3 = createIndexDetails("memberTwo", "/Employees", "empDobIdx");
-
- final List expectedIndexDetails =
- Arrays.asList(indexDetails1, indexDetails2, indexDetails3);
-
- final List> results = new ArrayList>(2);
-
- results.add(CollectionUtils.asSet(indexDetails2, indexDetails1));
- results.add(CollectionUtils.asSet(indexDetails3));
-
- mockContext.checking(new Expectations() {
- {
- oneOf(mockFunctionExecutor).setIgnoreDepartedMembers(with(equal(true)));
- oneOf(mockFunctionExecutor).execute(with(aNonNull(ListIndexFunction.class)));
- will(returnValue(mockResultCollector));
- oneOf(mockResultCollector).getResult();
- will(returnValue(results));
- }
- });
-
- final IndexCommands commands = createIndexCommands(mockCache, mockFunctionExecutor);
-
- final List actualIndexDetails = commands.getIndexListing();
-
- assertNotNull(actualIndexDetails);
- assertEquals(expectedIndexDetails, actualIndexDetails);
- }
-
- @Test(expected = RuntimeException.class)
- public void testGetIndexListingThrowsRuntimeException() {
- final InternalCache mockCache = mockContext.mock(InternalCache.class, "InternalCache");
-
- final Execution mockFunctionExecutor = mockContext.mock(Execution.class, "Function Executor");
-
- mockContext.checking(new Expectations() {
- {
- oneOf(mockFunctionExecutor).execute(with(aNonNull(ListIndexFunction.class)));
- will(throwException(new RuntimeException("expected")));
- }
- });
-
- final IndexCommands commands = createIndexCommands(mockCache, mockFunctionExecutor);
-
- try {
- commands.getIndexListing();
- } catch (RuntimeException expected) {
- assertEquals("expected", expected.getMessage());
- throw expected;
- }
- }
-
- @Test
- public void testGetIndexListingReturnsFunctionInvocationTargetExceptionInResults() {
- final InternalCache mockCache = mockContext.mock(InternalCache.class, "InternalCache");
-
- final AbstractExecution mockFunctionExecutor =
- mockContext.mock(AbstractExecution.class, "Function Executor");
-
- final ResultCollector mockResultCollector =
- mockContext.mock(ResultCollector.class, "ResultCollector");
-
- final IndexDetails indexDetails = createIndexDetails("memberOne", "/Employees", "empIdIdx");
-
- final List expectedIndexDetails = Arrays.asList(indexDetails);
-
- final List results = new ArrayList(2);
-
- results.add(CollectionUtils.asSet(indexDetails));
- results.add(new FunctionInvocationTargetException("expected"));
-
- mockContext.checking(new Expectations() {
- {
- oneOf(mockFunctionExecutor).setIgnoreDepartedMembers(with(equal(true)));
- oneOf(mockFunctionExecutor).execute(with(aNonNull(ListIndexFunction.class)));
- will(returnValue(mockResultCollector));
- oneOf(mockResultCollector).getResult();
- will(returnValue(results));
- }
- });
-
- final IndexCommands commands = createIndexCommands(mockCache, mockFunctionExecutor);
-
- final List actualIndexDetails = commands.getIndexListing();
-
- assertNotNull(actualIndexDetails);
- assertEquals(expectedIndexDetails, actualIndexDetails);
- }
-
- private static class TestIndexCommands extends IndexCommands {
-
- private final InternalCache cache;
- private final Execution functionExecutor;
-
- protected TestIndexCommands(final InternalCache cache, final Execution functionExecutor) {
- assert cache != null : "The InternalCache cannot be null!";
- assert functionExecutor != null : "The function executor cannot be null!";
- this.cache = cache;
- this.functionExecutor = functionExecutor;
- }
-
- @Override
- public InternalCache getCache() {
- return this.cache;
- }
-
- @Override
- public Set getMembers(final InternalCache cache) {
- assertSame(getCache(), cache);
- return Collections.emptySet();
- }
-
- @Override
- public Execution getMembersFunctionExecutor(final Set members) {
- Assert.assertNotNull(members);
- return functionExecutor;
- }
- }
-
-}