/* * 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.query.partitioned; import org.junit.experimental.categories.Category; import org.junit.Test; import static org.junit.Assert.*; import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; import org.apache.geode.test.junit.categories.DistributedTest; import static org.apache.geode.cache.query.Utils.*; import org.apache.geode.cache.Cache; import org.apache.geode.cache.Region; import org.apache.geode.cache.persistence.PartitionOfflineException; import org.apache.geode.cache.query.Index; import org.apache.geode.cache.query.IndexType; import org.apache.geode.cache.query.Query; import org.apache.geode.cache.query.QueryService; import org.apache.geode.cache.query.SelectResults; import org.apache.geode.cache.query.data.Portfolio; import org.apache.geode.cache.query.data.PortfolioData; import org.apache.geode.cache30.CacheSerializableRunnable; import org.apache.geode.internal.cache.PartitionedRegionDUnitTestCase; import org.apache.geode.test.dunit.AsyncInvocation; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.LogWriterUtils; import org.apache.geode.test.dunit.VM; /** * This tests creates partition regions with 1 Datastore & 1 Accessor node, firing a simple query * and validating the ResultSet size and Contents. * */ @Category(DistributedTest.class) public class PRBasicQueryDUnitTest extends PartitionedRegionDUnitTestCase { /** * constructor * * @param name */ public PRBasicQueryDUnitTest() { super(); } public void setCacheInVMs(VM... vms) { for (VM vm : vms) { vm.invoke(() -> PRQueryDUnitHelper.setCache(getCache())); } } private final static int MAX_SYNC_WAIT = 30 * 1000; PRQueryDUnitHelper PRQHelp = new PRQueryDUnitHelper(); final String name = "Portfolios"; final String localName = "LocalPortfolios"; final int cnt = 0, cntDest = 50; final int redundancy = 0; /** * A very basic dunit test that <br> * 1. Creates a PR Accessor and Data Store with redundantCopies = 0. 2. Populates the region with * test data. 3. Fires a query on accessor VM and verifies the result. * * @throws Exception */ @Test public void testPRBasicQuerying() throws Exception { Host host = Host.getHost(0); VM vm0 = host.getVM(0); VM vm1 = host.getVM(1); setCacheInVMs(vm0, vm1); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRBasicQuerying: Querying PR Test with DACK Started"); // Creting PR's on the participating VM's // Creating Accessor node on the VM0. LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRBasicQuerying: Creating the Accessor node in the PR"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRAccessorCreate(name, redundancy, PortfolioData.class)); // Creating local region on vm0 to compare the results of query. vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, PortfolioData.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testPRBasicQuerying: Successfully created the Accessor node in the PR"); // Creating the Datastores Nodes in the VM1. LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest:testPRBasicQuerying ----- Creating the Datastore node in the PR"); vm1.invoke( PRQHelp.getCacheSerializableRunnableForPRCreate(name, redundancy, PortfolioData.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testPRBasicQuerying: Successfully Created the Datastore node in the PR"); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testPRBasicQuerying: Successfully Created PR's across all VM's"); // Generating portfolio object array to be populated across the PR's & Local // Regions final PortfolioData[] portfolio = createPortfolioData(cnt, cntDest); // Putting the data into the PR's created vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(name, portfolio, cnt, cntDest)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(name, portfolio, cnt, cntDest)); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRBasicQuerying: Inserted Portfolio data across PR's"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(localName, portfolio, cnt, cntDest)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(localName, portfolio, cnt, cntDest)); // querying the VM for data and comparing the result with query result of // local region. // querying the VM for data vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRQueryAndCompareResults(name, localName)); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRBasicQuerying: Querying PR's Test ENDED"); } /** * A basic dunit test that <br> * 1. Creates a PR and colocated child region Accessor and Data Store with redundantCopies = 0. 2. * Populates the region with test data. 3. Fires a query on accessor VM and verifies the result. * 4. Shuts down the caches, then restarts them asynchronously 5. Attempt the query while the * regions are being recovered * * @throws Exception */ @Test public void testColocatedPRQueryDuringRecovery() throws Exception { Host host = Host.getHost(0); VM vm0 = host.getVM(0); VM vm1 = host.getVM(1); setCacheInVMs(vm0, vm1); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Querying PR Test with DACK Started"); // Creting PR's on the participating VM's // Creating Accessor node on the VM0. LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Creating the Accessor node in the PR"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForColocatedPRCreate(name, redundancy, PortfolioData.class, true)); // Creating local region on vm0 to compare the results of query. vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, PortfolioData.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully created the Accessor node in the PR"); // Creating the Datastores Nodes in the VM1. LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest:testColocatedPRBasicQuerying ----- Creating the Datastore node in the PR"); vm1.invoke(PRQHelp.getCacheSerializableRunnableForColocatedPRCreate(name, redundancy, PortfolioData.class, true)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully Created the Datastore node in the PR"); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully Created PR's across all VM's"); // Generating portfolio object array to be populated across the PR's & Local // Regions final PortfolioData[] portfolio = createPortfolioData(cnt, cntDest); // Putting the data into the PR's created vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(name, portfolio, cnt, cntDest)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(name, portfolio, cnt, cntDest)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Inserted Portfolio data across PR's"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(localName, portfolio, cnt, cntDest)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(localName, portfolio, cnt, cntDest)); // querying the VM for data and comparing the result with query result of // local region. // querying the VM for data vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRQueryAndCompareResults(name, localName)); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Querying PR's 1st pass ENDED"); // Shut everything down and then restart to test queries during recovery vm0.invoke(PRQHelp.getCacheSerializableRunnableForCloseCache()); vm1.invoke(PRQHelp.getCacheSerializableRunnableForCloseCache()); // Re-create the regions - only create the parent regions on the datastores setCacheInVMs(vm0, vm1); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Creating the Accessor node in the PR"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForColocatedParentCreate(name, redundancy, PortfolioData.class, true)); // Creating local region on vm0 to compare the results of query. vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, PortfolioData.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully created the Accessor node in the PR"); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest:testColocatedPRBasicQuerying: re-creating the Datastore node in the PR"); vm1.invoke(PRQHelp.getCacheSerializableRunnableForColocatedParentCreate(name, redundancy, PortfolioData.class, true)); // Now start the child regions asynchronously so queries will happen during persistent recovery AsyncInvocation vm0PR = vm0.invokeAsync(PRQHelp.getCacheSerializableRunnableForColocatedChildCreate(name, redundancy, PortfolioData.class, true)); AsyncInvocation vm1PR = vm1.invokeAsync(PRQHelp.getCacheSerializableRunnableForColocatedChildCreate(name, redundancy, PortfolioData.class, true)); // delay the query to let the recovery get underway Thread.sleep(100); try { // This is a repeat of the original query from before closing and restarting the datastores. // This time // it should fail due to persistent recovery that has not completed. vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRQueryAndCompareResults(name, localName, true)); fail( "Expected PartitionOfflineException when queryiong a region with offline colocated child"); } catch (Exception e) { if (!(e.getCause() instanceof PartitionOfflineException)) { e.printStackTrace(); throw e; } } LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Querying PR's 2nd pass (after restarting regions) ENDED"); } /** * A basic dunit test that <br> * 1. Creates a PR and colocated child region Accessor and Data Store with redundantCopies = 0. 2. * Populates the region with test data. 3. Fires a query on accessor VM and verifies the result. * 4. Shuts down the caches, then restarts them asynchronously, but don't restart the child region * 5. Attempt the query while the region offline because of the missing child region * * @throws Exception */ @SuppressWarnings("rawtypes") @Test public void testColocatedPRQueryDuringRecoveryWithMissingColocatedChild() throws Exception { Host host = Host.getHost(0); VM vm0 = host.getVM(0); VM vm1 = host.getVM(1); setCacheInVMs(vm0, vm1); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Querying PR Test with DACK Started"); // Creting PR's on the participating VM's // Creating Accessor node on the VM0. LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Creating the Accessor node in the PR"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForColocatedPRCreate(name, redundancy, PortfolioData.class, true)); // Creating local region on vm0 to compare the results of query. vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, PortfolioData.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully created the Accessor node in the PR"); // Creating the Datastores Nodes in the VM1. LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest:testColocatedPRBasicQuerying ----- Creating the Datastore node in the PR"); vm1.invoke(PRQHelp.getCacheSerializableRunnableForColocatedPRCreate(name, redundancy, PortfolioData.class, true)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully Created the Datastore node in the PR"); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully Created PR's across all VM's"); // Generating portfolio object array to be populated across the PR's & Local // Regions final PortfolioData[] portfolio = createPortfolioData(cnt, cntDest); // Putting the data into the PR's created vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(name, portfolio, cnt, cntDest)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(name, portfolio, cnt, cntDest)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Inserted Portfolio data across PR's"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(localName, portfolio, cnt, cntDest)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(localName, portfolio, cnt, cntDest)); // querying the VM for data and comparing the result with query result of // local region. // querying the VM for data vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRQueryAndCompareResults(name, localName)); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Querying PR's 1st pass ENDED"); // Shut everything down and then restart to test queries during recovery vm0.invoke(PRQHelp.getCacheSerializableRunnableForCloseCache()); vm1.invoke(PRQHelp.getCacheSerializableRunnableForCloseCache()); // Re-create the only the parent region setCacheInVMs(vm0, vm1); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Creating the Accessor node in the PR"); vm0.invoke(PRQHelp.getCacheSerializableRunnableForColocatedParentCreate(name, redundancy, PortfolioData.class, true)); // Creating local region on vm0 to compare the results of query. vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, PortfolioData.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Successfully created the Accessor node in the PR"); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest:testColocatedPRBasicQuerying ----- re-creating the Datastore node in the PR"); vm1.invoke(PRQHelp.getCacheSerializableRunnableForColocatedParentCreate(name, redundancy, PortfolioData.class, true)); try { // This is a repeat of the original query from before closing and restarting the datastores. // This time // it should fail due to persistent recovery that has not completed. vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRQueryAndCompareResults(name, localName, true)); fail( "Expected PartitionOfflineException when queryiong a region with offline colocated child"); } catch (Exception e) { if (!(e.getCause() instanceof PartitionOfflineException)) { throw e; } } LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testColocatedPRBasicQuerying: Querying PR's 2nd pass (after restarting regions) ENDED"); } @Test public void testPRCountStarQuery() throws Exception { Host host = Host.getHost(0); VM vm0 = host.getVM(0); VM vm1 = host.getVM(1); VM vm2 = host.getVM(2); setCacheInVMs(vm0, vm1, vm2); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRCountStarQuery: Querying PR Test with DACK Started"); // Creting PR's on the participating VM's // Creating Accessor node on the VM0. LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRCountStarQuery: Creating the Accessor node in the PR"); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRAccessorCreate(name, redundancy, Portfolio.class)); // Creating local region on vm0 to compare the results of query. vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, Portfolio.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testPRCountStarQuery: Successfully created the Accessor node in the PR"); // Creating the Datastores Nodes in the VM1. LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest:testPRCountStarQuery ----- Creating the Datastore node in the PR"); vm1.invoke(PRQHelp.getCacheSerializableRunnableForPRCreate(name, redundancy, Portfolio.class)); vm2.invoke(PRQHelp.getCacheSerializableRunnableForPRCreate(name, redundancy, Portfolio.class)); vm2.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, Portfolio.class)); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testPRCountStarQuery: Successfully Created the Datastore node in the PR"); LogWriterUtils.getLogWriter().info( "PRQBasicQueryDUnitTest#testPRCountStarQuery: Successfully Created PR's across all VM's"); // Generating portfolio object array to be populated across the PR's & Local // Regions final Portfolio[] portfolio = createPortfoliosAndPositions(cntDest + 100); // Putting the data into the PR's created vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRPuts(name, portfolio, cnt, cntDest + 100)); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(name, portfolio, cnt, cntDest + 100)); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRCountStarQuery: Inserted Portfolio data across PR's"); vm0.invoke( PRQHelp.getCacheSerializableRunnableForPRPuts(localName, portfolio, cnt, cntDest + 100)); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(localName, portfolio, cnt, cntDest + 100)); vm2.invoke( PRQHelp.getCacheSerializableRunnableForPRPuts(localName, portfolio, cnt, cntDest + 100)); vm2.invoke(PRQHelp.getCacheSerializableRunnableForPRDuplicatePuts(localName, portfolio, cnt, cntDest + 100)); // querying the VM for data and comparing the result with query result of // local region. // querying the VM for data vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRCountStarQueries(name, localName)); vm2.invoke(PRQHelp.getCacheSerializableRunnableForPRCountStarQueries(name, localName)); LogWriterUtils.getLogWriter() .info("PRQBasicQueryDUnitTest#testPRCountStarQuery: Querying PR's Test ENDED"); } @Test public void testPROrderBy() throws Exception { Host host = Host.getHost(0); VM vm0 = host.getVM(0); VM vm1 = host.getVM(1); setCacheInVMs(vm0, vm1); vm0.invoke(PRQHelp.getCacheSerializableRunnableForPRAccessorCreate(name, redundancy, PortfolioData.class)); vm0.invoke( PRQHelp.getCacheSerializableRunnableForLocalRegionCreation(localName, PortfolioData.class)); vm1.invoke(PRQHelp.getCacheSerializableRunnableForPRCreate(name, redundancy, Portfolio.class)); vm1.invoke(new CacheSerializableRunnable("Adding portfolios") { public void run2() { Cache cache = getCache(); Region region = cache.getRegion(name); for (int j = 0; j < 100; j++) region.put(new Integer(j), new Portfolio(j)); } }); vm1.invoke(new CacheSerializableRunnable("Running Query") { public void run2() { try { QueryService qs = null; qs = getCache().getQueryService(); Index d = qs.createIndex("index", IndexType.FUNCTIONAL, "ID", "/" + name); for (int i = 0; i < 100; i++) { Query query = qs.newQuery("SELECT DISTINCT * FROM /" + name + " WHERE ID >= " + i + " ORDER BY ID asc LIMIT 1"); SelectResults results = (SelectResults) query.execute(); int expectedValue = i; for (Object o : results) { Portfolio p = (Portfolio) o; assert (p.getID() == expectedValue++); } } } catch (Exception e) { e.printStackTrace(); fail("exception:" + e); } } }); } }