/* * 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.cache.lucene.internal.configuration; import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.*; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.apache.geode.internal.AvailablePortHelper.*; import static org.junit.Assert.*; import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Map; import java.util.Properties; import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; import org.apache.geode.test.dunit.rules.Member; import org.apache.lucene.analysis.Analyzer; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.cache.RegionShortcut; import org.apache.geode.cache.lucene.LuceneIndex; import org.apache.geode.cache.lucene.LuceneService; import org.apache.geode.cache.lucene.LuceneServiceProvider; import org.apache.geode.cache.lucene.internal.cli.LuceneCliStrings; import org.apache.geode.cache.lucene.internal.cli.LuceneIndexCommands; import org.apache.geode.management.cli.Result.Status; import org.apache.geode.management.internal.cli.CommandManager; import org.apache.geode.management.internal.cli.HeadlessGfsh; import org.apache.geode.management.internal.cli.commands.CliCommandTestBase; import org.apache.geode.management.internal.cli.i18n.CliStrings; import org.apache.geode.management.internal.cli.result.CommandResult; import org.apache.geode.management.internal.cli.util.CommandStringBuilder; import org.apache.geode.test.dunit.VM; import org.apache.geode.test.junit.categories.DistributedTest; @Category(DistributedTest.class) public class LuceneClusterConfigurationDUnitTest extends CliCommandTestBase { private String groupName = "Lucene"; @Rule public LocatorServerStartupRule ls = new LocatorServerStartupRule(); @Test public void indexGetsCreatedUsingClusterConfiguration() throws Exception { Member locator = startLocatorWithClusterConfigurationEnabled(); Member vm1 = startNodeUsingClusterConfiguration(1, false); // Connect Gfsh to locator. createAndConnectGfshToLocator(); // Create lucene index. createLuceneIndexUsingGfsh(false); createRegionUsingGfsh(REGION_NAME, RegionShortcut.PARTITION, null); // Start vm2. This should have lucene index created using cluster // configuration. Member vm2 = startNodeUsingClusterConfiguration(2, false); vm2.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNotNull(index); validateIndexFields(new String[] {"field1", "field2", "field3"}, index); }); } @Test public void indexWithAnalyzerGetsCreatedUsingClusterConfiguration() throws Exception { Member locator = startLocatorWithClusterConfigurationEnabled(); Member vm1 = startNodeUsingClusterConfiguration(1, false); // Connect Gfsh to locator. createAndConnectGfshToLocator(); // Create lucene index. // createLuceneIndexUsingGfsh(false); createLuceneIndexWithAnalyzerUsingGfsh(false); createRegionUsingGfsh(REGION_NAME, RegionShortcut.PARTITION, null); // Start vm2. This should have lucene index created using cluster // configuration. Member vm2 = startNodeUsingClusterConfiguration(2, false); vm2.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNotNull(index); String[] fields = new String[] {"field1", "field2", "field3"}; validateIndexFields(fields, index); // Add this check back when we complete xml generation for analyzer. this.validateIndexFieldAnalyzer(fields, new String[] {"org.apache.lucene.analysis.standard.StandardAnalyzer", "org.apache.lucene.analysis.standard.StandardAnalyzer", "org.apache.lucene.analysis.standard.StandardAnalyzer"}, index); }); } @Test public void indexGetsCreatedOnGroupOfNodes() throws Exception { Member locator = startLocatorWithClusterConfigurationEnabled(); // Start vm1, vm2 in group Member vm1 = startNodeUsingClusterConfiguration(1, true); Member vm2 = startNodeUsingClusterConfiguration(2, true); // Start vm3 outside the group. The Lucene index should not be present here. Member vm3 = startNodeUsingClusterConfiguration(3, true); // Connect Gfsh to locator. createAndConnectGfshToLocator(); // Create lucene index on group. createLuceneIndexUsingGfsh(true); // Create region. createRegionUsingGfsh(REGION_NAME, RegionShortcut.PARTITION, groupName); // VM2 should have lucene index created using gfsh execution. vm2.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNotNull(index); validateIndexFields(new String[] {"field1", "field2", "field3"}, index); }); // The Lucene index is present in vm3. vm3.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNotNull(index); }); } @Test public void indexNotCreatedOnNodeOutSideTheGroup() throws Exception { Member locator = startLocatorWithClusterConfigurationEnabled(); // Start vm1, vm2 in group Member vm1 = startNodeUsingClusterConfiguration(1, true); Member vm2 = startNodeUsingClusterConfiguration(2, true); // Start vm3 outside the group. The Lucene index should not be present here. Member vm3 = startNodeUsingClusterConfiguration(3, false); // Connect Gfsh to locator. createAndConnectGfshToLocator(); // Create lucene index on group. createLuceneIndexUsingGfsh(true); // Create region. createRegionUsingGfsh(REGION_NAME, RegionShortcut.PARTITION, groupName); // VM2 should have lucene index created using gfsh execution vm2.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNotNull(index); validateIndexFields(new String[] {"field1", "field2", "field3"}, index); }); // The Lucene index should not be present in vm3. vm3.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNull(index); }); } @Test public void indexAreCreatedInValidGroupOfNodesJoiningLater() throws Exception { Member locator = startLocatorWithClusterConfigurationEnabled(); // Start vm1 in group Member vm1 = startNodeUsingClusterConfiguration(1, true); // Connect Gfsh to locator. createAndConnectGfshToLocator(); // Create lucene index on group. createLuceneIndexUsingGfsh(true); createRegionUsingGfsh(REGION_NAME, RegionShortcut.PARTITION, groupName); // Start vm2 in group Member vm2 = startNodeUsingClusterConfiguration(2, true); // Start vm3 outside the group. The Lucene index should not be present here. Member vm3 = startNodeUsingClusterConfiguration(3, false); // VM2 should have lucene index created using gfsh execution vm2.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNotNull(index); validateIndexFields(new String[] {"field1", "field2", "field3"}, index); }); // The Lucene index should not be present in vm3. vm3.invoke(() -> { LuceneService luceneService = LuceneServiceProvider.get(ls.serverStarter.cache); final LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); assertNull(index); }); } private void createAndConnectGfshToLocator() { HeadlessGfsh gfsh = getDefaultShell(); connect(jmxHost, jmxPort, httpPort, gfsh); } private Member startNodeUsingClusterConfiguration(int vmIndex, boolean addGroup) throws Exception { File dir = this.temporaryFolder.newFolder(); Properties nodeProperties = new Properties(); nodeProperties.setProperty(USE_CLUSTER_CONFIGURATION, "true"); nodeProperties.setProperty(DEPLOY_WORKING_DIR, dir.getCanonicalPath()); if (addGroup) { nodeProperties.setProperty(GROUPS, groupName); } return ls.startServerVM(vmIndex, nodeProperties, ls.getMember(0).getPort()); } private Member startLocatorWithClusterConfigurationEnabled() throws Exception { try { jmxHost = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException ignore) { jmxHost = "localhost"; } File dir = this.temporaryFolder.newFolder(); final int[] ports = getRandomAvailableTCPPorts(2); jmxPort = ports[0]; httpPort = ports[1]; Properties locatorProps = new Properties(); locatorProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "true"); locatorProps.setProperty(JMX_MANAGER, "true"); locatorProps.setProperty(JMX_MANAGER_START, "true"); locatorProps.setProperty(JMX_MANAGER_BIND_ADDRESS, String.valueOf(jmxHost)); locatorProps.setProperty(JMX_MANAGER_PORT, String.valueOf(jmxPort)); locatorProps.setProperty(HTTP_SERVICE_PORT, String.valueOf(httpPort)); locatorProps.setProperty(CLUSTER_CONFIGURATION_DIR, dir.getCanonicalPath()); return ls.startLocatorVM(0, locatorProps); } private void createLuceneIndexUsingGfsh(boolean addGroup) throws Exception { // Execute Gfsh command to create lucene index. CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance()); CommandStringBuilder csb = new CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX); csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME, INDEX_NAME); csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH, REGION_NAME); if (addGroup) { csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__GROUP, groupName); } csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD, "field1,field2,field3"); executeCommand(csb.toString()); } private void createLuceneIndexWithAnalyzerUsingGfsh(boolean addGroup) throws Exception { // Gfsh command to create lucene index. CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance()); CommandStringBuilder csb = new CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX); csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME, INDEX_NAME); csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH, REGION_NAME); csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD, "field1,field2,field3"); csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER, "org.apache.lucene.analysis.standard.StandardAnalyzer," + "org.apache.lucene.analysis.standard.StandardAnalyzer," + "org.apache.lucene.analysis.standard.StandardAnalyzer"); if (addGroup) { csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__GROUP, groupName); } // Execute Gfsh command. executeCommand(csb.toString()); } private void createRegionUsingGfsh(String regionName, RegionShortcut regionShortCut, String group) { CommandStringBuilder csb = new CommandStringBuilder(CliStrings.CREATE_REGION); csb.addOption(CliStrings.CREATE_REGION__REGION, regionName); csb.addOption(CliStrings.CREATE_REGION__REGIONSHORTCUT, regionShortCut.name()); csb.addOptionWithValueCheck(CliStrings.CREATE_REGION__GROUP, group); executeAndVerifyCommand(csb.toString()); } private void executeAndVerifyCommand(String commandString) { CommandResult cmdResult = executeCommand(commandString); org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("Command : " + commandString); org.apache.geode.test.dunit.LogWriterUtils.getLogWriter() .info("Command Result : " + commandResultToString(cmdResult)); assertEquals(Status.OK, cmdResult.getStatus()); } private void validateIndexFields(String[] indexFields, LuceneIndex index) { String[] indexFieldNames = index.getFieldNames(); Arrays.sort(indexFieldNames); assertArrayEquals(indexFields, indexFieldNames); } private void validateIndexFieldAnalyzer(String[] fields, String[] analyzers, LuceneIndex index) { Map<String, Analyzer> indexfieldAnalyzers = index.getFieldAnalyzers(); for (int i = 0; i < fields.length; i++) { Analyzer a = indexfieldAnalyzers.get(fields[i]); System.out.println("#### Analyzer name :" + a.getClass().getName()); assertEquals(analyzers[i], a.getClass().getName()); } } }