/*
* 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.internal.cache;
import org.apache.geode.DataSerializable;
import org.apache.geode.cache.query.Struct;
import org.apache.geode.cache.query.internal.index.AbstractIndex;
import org.apache.geode.pdx.PdxReader;
import org.apache.geode.pdx.PdxSerializable;
import org.apache.geode.pdx.PdxWriter;
import org.apache.geode.test.dunit.DUnitEnv;
import org.apache.geode.test.dunit.SerializableRunnableIF;
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.junit.categories.DistributedTest;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.IntStream;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.control.RebalanceOperation;
import org.apache.geode.cache.control.RebalanceResults;
import org.apache.geode.cache.query.Index;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.IndexExistsException;
import org.apache.geode.cache.query.IndexNameConflictException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.Query;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.RegionNotFoundException;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.cache.query.internal.index.IndexManager;
import org.apache.geode.cache.query.internal.index.PartitionedIndex;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.DistributionMessage;
import org.apache.geode.distributed.internal.DistributionMessageObserver;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache30.CacheSerializableRunnable;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.cache.partitioned.QueryMessage;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.test.dunit.Assert;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.SerializableCallable;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
/**
*
*/
@Category(DistributedTest.class)
public class PartitionedRegionQueryDUnitTest extends JUnit4CacheTestCase {
public PartitionedRegionQueryDUnitTest() {
super();
// TODO Auto-generated constructor stub
}
private static final AtomicReference<RebalanceResults> rebalanceResults =
new AtomicReference<RebalanceResults>();
@Test
public void testReevaluationDueToUpdateInProgress() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
// VM vm2 = host.getVM(2);
createPR(vm0);
createPR(vm1);
createIndex(vm0, "compactRangeIndex", "entry.value", "/region.entrySet entry");
// Do Puts
vm0.invoke(new SerializableRunnable("putting data") {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
for (int i = 0; i < 100; i++) {
region.put(i, new TestObject(i));
}
}
});
vm0.invoke(new SerializableRunnable("resetting sqt") {
public void run() {
IndexManager.setIndexBufferTime(Long.MAX_VALUE, Long.MAX_VALUE);
}
});
vm1.invoke(new SerializableRunnable("resetting sqt") {
public void run() {
IndexManager.setIndexBufferTime(Long.MAX_VALUE, Long.MAX_VALUE);
}
});
vm0.invoke(new SerializableRunnable("query") {
public void run() {
try {
QueryService qs = getCache().getQueryService();
qs.newQuery(
"SELECT DISTINCT entry.key, entry.value FROM /region.entrySet entry WHERE entry.value.score >= 5 AND entry.value.score <= 10 ORDER BY value asc")
.execute();
} catch (QueryInvocationTargetException e) {
e.printStackTrace();
fail(e.toString());
} catch (NameResolutionException e) {
fail(e.toString());
} catch (TypeMismatchException e) {
fail(e.toString());
} catch (FunctionDomainException e) {
fail(e.toString());
}
}
});
}
@Test
public void testHashIndexDoesNotDeserializePdxObjects() {
SerializableRunnableIF createIndex = () -> {
Cache cache = getCache();
cache.getQueryService().createHashIndex("ContractDocumentIndex", "document", "/region");
};
String queryString = "select assetId,document from /region where document='B' limit 1000";
PdxAssetFactory value = i -> new PdxNotDeserializableAsset(i, Integer.toString(i));
createIndexDoesNotDerializePdxObjects(createIndex, queryString, value);
}
@Test
public void tesRangeIndexDoesNotDeserializePdxObjects() {
SerializableRunnableIF createIndex = () -> {
Cache cache = getCache();
cache.getQueryService().createIndex("ContractDocumentIndex", "ref",
"/region r, r.references ref");
};
String queryString =
"select r.assetId,r.document from /region r, r.references ref where ref='B_2' limit 1000";
PdxAssetFactory value = i -> new PdxNotDeserializableAsset(i, Integer.toString(i));
createIndexDoesNotDerializePdxObjects(createIndex, queryString, value);
}
@Test
public void tesRangeIndexWithPdxObjects() {
SerializableRunnableIF createIndex = () -> {
Cache cache = getCache();
cache.getQueryService().createIndex("ContractDocumentIndex", "ref",
"/region r, r.references ref");
};
String queryString = "select r from /region r, r.references ref where ref='B_2' limit 1000";
PdxAssetFactory value = i -> new PdxAsset(i, Integer.toString(i));
createIndexDoesNotDerializePdxObjects(createIndex, queryString, value);
}
private void createIndexDoesNotDerializePdxObjects(final SerializableRunnableIF createIndex,
final String queryString, PdxAssetFactory valueSupplier) {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
SerializableRunnableIF createPR = () -> {
Cache cache = getCache();
PartitionAttributesFactory paf = new PartitionAttributesFactory();
paf.setTotalNumBuckets(10);
cache.createRegionFactory(RegionShortcut.PARTITION).setPartitionAttributes(paf.create())
.create("region");
};
vm0.invoke(createPR);
vm1.invoke(createPR);
// Do Puts. These objects can't be deserialized because they throw
// and exception from the constructor
vm0.invoke(() -> {
Cache cache = getCache();
Region region = cache.getRegion("region");
region.put(0, new PdxNotDeserializableAsset(0, "B"));
region.put(10, new PdxNotDeserializableAsset(1, "B"));
region.put(1, new PdxNotDeserializableAsset(1, "B"));
IntStream.range(11, 100).forEach(i -> region.put(i, valueSupplier.getAsset(i)));
});
// If this tries to deserialize the assets, it will fail
vm0.invoke(createIndex);
vm0.invoke(() -> {
QueryService qs = getCache().getQueryService();
SelectResults<Struct> results = (SelectResults) qs.newQuery(queryString).execute();
assertEquals(3, results.size());
final Index index = qs.getIndex(getCache().getRegion("region"), "ContractDocumentIndex");
assertEquals(1, index.getStatistics().getTotalUses());
});
}
@Test
public void testFailureToCreateIndexOnLocalNodeThrowsException() {
VM vmToFailCreationOn = Host.getHost(0).getVM(0);
failToCreateIndexOnNode(vmToFailCreationOn);
}
@Test
public void testFailureToCreateIndexOnRemoteNodeThrowsException() {
VM vmToFailCreationOn = Host.getHost(0).getVM(1);
failToCreateIndexOnNode(vmToFailCreationOn);
}
private void failToCreateIndexOnNode(final VM vmToFailCreationOn) {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
SerializableRunnableIF createPR = () -> {
Cache cache = getCache();
PartitionAttributesFactory paf = new PartitionAttributesFactory();
paf.setTotalNumBuckets(10);
cache.createRegionFactory(RegionShortcut.PARTITION).setPartitionAttributes(paf.create())
.create("region");
};
vm0.invoke(createPR);
vm1.invoke(createPR);
vm0.invoke(() -> {
Cache cache = getCache();
Region region = cache.getRegion("region");
IntStream.range(1, 10)
.forEach(i -> region.put(i, new NotDeserializableAsset(vmToFailCreationOn.getPid())));
});
vm0.invoke(() -> {
Cache cache = getCache();
try {
cache.getQueryService().createHashIndex("ContractDocumentIndex", "document", "/region");
fail("Should have thrown an exception");
} catch (Exception expected) {
}
});
vm1.invoke(() -> {
Cache cache = getCache();
Region region = cache.getRegion("region");
final AbstractIndex index =
(AbstractIndex) cache.getQueryService().getIndex(region, "ContractDocumentIndex");
// either the index was not created locally or it was created but is populated flag should not
// be set.
if (index != null) {
assertFalse(index.isPopulated());
}
});
}
/**
* Test of bug 43102. 1. Buckets are created on several nodes 2. A query is started 3. While the
* query is executing, several buckets are moved.
*/
@Test
public void testRebalanceDuringQueryEvaluation() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createBuckets(vm1);
createPR(vm2);
// Add a listener that will trigger a rebalance
// as soon as the query arrives on this node.
vm1.invoke(new SerializableRunnable("add listener") {
public void run() {
DistributionMessageObserver.setInstance(new DistributionMessageObserver() {
@Override
public void beforeProcessMessage(DistributionManager dm, DistributionMessage message) {
if (message instanceof QueryMessage) {
RebalanceOperation rebalance =
getCache().getResourceManager().createRebalanceFactory().start();
// wait for the rebalance
try {
rebalanceResults.compareAndSet(null, rebalance.getResults());
} catch (CancellationException e) {
// ignore
} catch (InterruptedException e) {
// ignore
}
}
}
});
}
});
executeQuery(vm0);
vm1.invoke(new SerializableRunnable("check rebalance happened") {
public void run() {
assertNotNull(rebalanceResults.get());
assertEquals(5, rebalanceResults.get().getTotalBucketTransfersCompleted());
}
});
}
/**
* Test of bug 50749 1. Indexes and Buckets are created on several nodes 2. Buckets are moved 3.
* Check to make sure we don't have lingering bucket indexes with bucket regions already destroyed
*/
@Test
public void testRebalanceWithIndex() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
VM vm3 = host.getVM(3);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createIndex(vm1, "prIndex", "r.score", "/region r");
// Do Puts
vm1.invoke(new SerializableRunnable("putting data") {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
for (int i = 0; i < 2000; i++) {
region.put(i, new TestObject(i));
}
}
});
createPR(vm3);
// Rebalance
vm1.invoke(new SerializableRunnable("rebalance") {
public void run() {
RebalanceOperation rebalance =
getCache().getResourceManager().createRebalanceFactory().start();
// wait for the rebalance
try {
rebalance.getResults();
} catch (CancellationException e) {
// ignore
} catch (InterruptedException e) {
// ignore
}
}
});
checkForLingeringBucketIndexes(vm1, "prIndex");
checkForLingeringBucketIndexes(vm2, "prIndex");
closeCache(vm1, vm2, vm3, vm0);
}
/**
* tests trace for pr queries when <trace> is used and query verbose is set to true on local and
* remote servers
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOnBothServers() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query =
cache.getQueryService().newQuery("<trace> select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
// verify hooks
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertTrue(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is used and query verbose is set to true on local but
* false on remote servers All flags should be true still as the <trace> is OR'd with query
* verbose flag
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOnLocalServerOnly() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query =
cache.getQueryService().newQuery("<trace> select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertTrue(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is NOT used and query verbose is set to true on local
* but false on remote The remote should not send a pr query trace info back because trace was not
* requested
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOffLocalServerVerboseOn() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query = cache.getQueryService().newQuery("select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertNull(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertNull(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertNull(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is NOT used and query verbose is set to false on local
* but true on remote servers We don't output the string or do anything on the local side, but we
* still pull off the object due to the remote server generating and sending it over
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOffRemoteServerOnly() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query = cache.getQueryService().newQuery("select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
// verify hooks
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertNull(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertNull(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertTrue(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is used and query verbose is set to false on local and
* remote servers trace is OR'd so the entire trace process should be invoked
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOnRemoteServerOnly() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query =
cache.getQueryService().newQuery("<trace> select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
// verify hooks
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertTrue(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is NOT used and query verbose is set to false on local
* but true remote servers The local node still receives the pr trace info from the remote node
* due to query verbose being on however nothing is used on the local side
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOffRemoteServerOn() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = true;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query = cache.getQueryService().newQuery("select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
// verify hooks
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertNull(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertNull(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertTrue(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is NOT used and query verbose is set to false on local
* and remote servers None of our hooks should have triggered
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOffQueryVerboseOff() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query = cache.getQueryService().newQuery("select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
// verify hooks
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertNull(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertNull(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertNull(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertNull(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertNull(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
/**
* tests trace for pr queries when <trace> is used and query verbose is set to false on local and
* remote servers All hooks should have triggered due to trace being used
*/
@Test
public void testPartitionRegionDebugMessageQueryTraceOnQueryVerboseOff() {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
VM vm1 = host.getVM(1);
VM vm2 = host.getVM(2);
createAccessor(vm0);
createPR(vm1);
createPR(vm2);
createBuckets(vm1);
final PRQueryTraceTestHook server1TestHook = new PRQueryTraceTestHook();
final PRQueryTraceTestHook server2TestHook = new PRQueryTraceTestHook();
try {
vm1.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server1TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.testHook = server2TestHook;
DefaultQuery.QUERY_VERBOSE = false;
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query =
cache.getQueryService().newQuery("<trace> select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
vm1.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server1TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server1TestHook.getHooks().get("Pull off PR Query Trace Info"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace String"));
assertTrue(server1TestHook.getHooks().get("Create PR Query Trace Info From Local Node"));
}
});
vm2.invoke(new SerializableRunnable() {
public void run() {
PRQueryTraceTestHook server2TestHook = (PRQueryTraceTestHook) DefaultQuery.testHook;
assertTrue(server2TestHook.getHooks().get("Populating Trace Info for Remote Query"));
assertTrue(server2TestHook.getHooks().get("Create PR Query Trace Info for Remote Query"));
}
});
} finally {
setQueryVerbose(false, vm1, vm2);
}
}
@Test
public void testOrderByOnPRWithReservedKeywords() throws Exception {
final Host host = Host.getHost(0);
final VM server1 = host.getVM(0);
final VM server2 = host.getVM(1);
final VM client = host.getVM(2);
final String regionName = "region1";
final String[] queries = {"select distinct * from /" + regionName + " order by \"date\"",
"select distinct \"date\" from /" + regionName + " order by \"date\"",
"select distinct * from /" + regionName + " order by \"time\"",
"select distinct \"time\" from /" + regionName + " order by \"time\"",
"select distinct * from /" + regionName + " order by \"timestamp\"",
"select distinct \"timestamp\" from /" + regionName + " order by \"timestamp\"",
"select distinct \"date\" from /" + regionName + " order by \"date\".\"score\"",
"select distinct * from /" + regionName + " order by nested.\"date\"",
"select distinct * from /" + regionName + " order by nested.\"date\".nonKeyword",
"select distinct * from /" + regionName + " order by nested.\"date\".\"date\"",
"select distinct * from /" + regionName + " order by nested.\"date\".\"date\".score",};
// Start server1
final Integer port1 = (Integer) server1.invoke(new SerializableCallable("Create Server1") {
@Override
public Object call() throws Exception {
String jsonCustomer = "{" + "\"firstName\": \"John\"," + "\"lastName\": \"Smith\","
+ " \"age\": 25," + " \"date\":" + " \"" + new java.util.Date() + "\"," + " \"time\":"
+ " \"" + new java.sql.Time(1000) + "\"," + " \"timestamp\":" + " \""
+ new java.sql.Timestamp(1000) + "\"" + "}";
String jsonCustomer1 = "{" + "\"firstName\": \"John1\"," + "\"lastName\": \"Smith1\","
+ " \"age\": 25," + " \"date\":" + " \"" + new java.util.Date() + "\"," + " \"time\":"
+ " \"" + new java.sql.Time(1000) + "\"," + " \"timestamp\":" + " \""
+ new java.sql.Timestamp(1000) + "\"" + "}";
String jsonCustomer2 = "{" + "\"firstName\": \"John2\"," + "\"lastName\": \"Smith2\","
+ " \"age\": 25," + " \"date\":" + " \"" + new java.util.Date() + "\"," + " \"time\":"
+ " \"" + new java.sql.Time(1000) + "\"," + " \"timestamp\":" + " \""
+ new java.sql.Timestamp(1000) + "\"" + "}";
String jsonCustomer3 = "{" + "\"firstName\": \"John3\"," + "\"lastName\": \"Smith3\","
+ " \"age\": 25," + " \"date\":" + " \"" + new TestObject(1) + "\"," + " \"time\":"
+ " \"" + new java.sql.Time(1000) + "\"," + " \"timestamp\":" + " \""
+ new java.sql.Timestamp(1000) + "\"" + "}";
String jsonCustomer4 = "{" + "\"firstName\": \"John4\"," + "\"lastName\": \"Smith4\","
+ " \"age\": 25," + " \"date\":" + " \"" + new TestObject(1) + "\"," + " \"time\":"
+ " \"" + new java.sql.Time(1000) + "\"," + " \"timestamp\":" + " \""
+ new java.sql.Timestamp(1000) + "\"," + " \"nested\":" + " \""
+ new NestedKeywordObject(1) + "\"" + "}";
String jsonCustomer5 = "{" + "\"firstName\": \"John5\"," + "\"lastName\": \"Smith5\","
+ " \"age\": 25," + " \"date\":" + " \"" + new TestObject(1) + "\"," + " \"time\":"
+ " \"" + new java.sql.Time(1000) + "\"," + " \"timestamp\":" + " \""
+ new java.sql.Timestamp(1000) + "\"," + " \"nested\":" + " \""
+ new NestedKeywordObject(new NestedKeywordObject(new TestObject(1))) + "\"" + "}";
Region r1 = getCache().createRegionFactory(RegionShortcut.PARTITION).create(regionName);
r1.put("jsondoc", JSONFormatter.fromJSON(jsonCustomer));
r1.put("jsondoc1", JSONFormatter.fromJSON(jsonCustomer1));
r1.put("jsondoc2", JSONFormatter.fromJSON(jsonCustomer2));
r1.put("jsondoc3", JSONFormatter.fromJSON(jsonCustomer3));
r1.put("jsondoc4", JSONFormatter.fromJSON(jsonCustomer4));
r1.put("jsondoc5", JSONFormatter.fromJSON(jsonCustomer5));
CacheServer server = getCache().addCacheServer();
int port = AvailablePortHelper.getRandomAvailablePortForDUnitSite();
server.setPort(port);
server.start();
return port;
}
});
// Start server2
final Integer port2 = (Integer) server2.invoke(new SerializableCallable("Create Server2") {
@Override
public Object call() throws Exception {
Region r1 = getCache().createRegionFactory(RegionShortcut.PARTITION).create(regionName);
CacheServer server = getCache().addCacheServer();
int port = AvailablePortHelper.getRandomAvailablePortForDUnitSite();
server.setPort(port);
server.start();
return port;
}
});
client.invoke(new SerializableCallable("Create client") {
@Override
public Object call() throws Exception {
ClientCacheFactory cf = new ClientCacheFactory();
cf.addPoolServer(NetworkUtils.getServerHostName(server1.getHost()), port1);
cf.addPoolServer(NetworkUtils.getServerHostName(server2.getHost()), port2);
ClientCache cache = getClientCache(cf);
Region region =
cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName);
QueryService qs = null;
SelectResults sr = null;
try {
qs = getCache().getQueryService();
} catch (Exception e) {
Assert.fail("Failed to get QueryService.", e);
}
for (int i = 0; i < queries.length; i++) {
try {
sr = (SelectResults) qs.newQuery(queries[i]).execute();
assertTrue("Size of resultset should be greater than 0 for query: " + queries[i],
sr.size() > 0);
} catch (Exception e) {
Assert.fail("Failed executing query ", e);
}
}
return null;
}
});
this.closeClient(server1);
this.closeClient(server2);
this.closeClient(client);
}
/* Close Client */
public void closeClient(VM client) {
SerializableRunnable closeCache = new CacheSerializableRunnable("Close Client") {
public void run2() throws CacheException {
LogWriterUtils.getLogWriter().info("### Close Client. ###");
try {
closeCache();
disconnectFromDS();
} catch (Exception ex) {
LogWriterUtils.getLogWriter().info("### Failed to get close client. ###");
}
}
};
client.invoke(closeCache);
}
private void executeQuery(VM vm0) {
vm0.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
Query query = cache.getQueryService().newQuery("select * from /region r where r > 0");
try {
SelectResults results = (SelectResults) query.execute();
assertEquals(new HashSet(Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9})),
results.asSet());
} catch (Exception e) {
Assert.fail("Bad query", e);
}
}
});
}
private void checkForLingeringBucketIndexes(VM vm, final String indexName) {
vm.invoke(new SerializableRunnable() {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
QueryService qs = cache.getQueryService();
PartitionedIndex index = (PartitionedIndex) qs.getIndex(region, indexName);
Iterator iterator = index.getBucketIndexes().iterator();
int numBucketIndexes = index.getBucketIndexes().size();
while (iterator.hasNext()) {
Index bucketIndex = (Index) iterator.next();
assertFalse(((LocalRegion) bucketIndex.getRegion()).isDestroyed());
}
}
});
}
private void createBuckets(VM vm) {
vm.invoke(new SerializableRunnable("create accessor") {
public void run() {
Cache cache = getCache();
Region region = cache.getRegion("region");
for (int i = 0; i < 10; i++) {
region.put(i, i);
}
}
});
}
private void createPR(VM vm) {
vm.invoke(new SerializableRunnable("create accessor") {
public void run() {
Cache cache = getCache();
PartitionAttributesFactory paf = new PartitionAttributesFactory();
paf.setTotalNumBuckets(10);
cache.createRegionFactory(RegionShortcut.PARTITION).setPartitionAttributes(paf.create())
.create("region");
}
});
}
private void createAccessor(VM vm) {
vm.invoke(new SerializableRunnable("create accessor") {
public void run() {
Cache cache = getCache();
PartitionAttributesFactory paf = new PartitionAttributesFactory();
paf.setTotalNumBuckets(10);
paf.setLocalMaxMemory(0);
cache.createRegionFactory(RegionShortcut.PARTITION_PROXY)
.setPartitionAttributes(paf.create()).create("region");
}
});
}
private void createIndex(VM vm, final String indexName, final String indexedExpression,
final String regionPath) {
vm.invoke(new SerializableRunnable("create index") {
public void run() {
try {
Cache cache = getCache();
cache.getQueryService().createIndex(indexName, indexedExpression, regionPath);
} catch (RegionNotFoundException e) {
fail(e.toString());
} catch (IndexExistsException e) {
fail(e.toString());
} catch (IndexNameConflictException e) {
fail(e.toString());
}
}
});
}
private void closeCache(VM... vms) {
for (VM vm : vms) {
vm.invoke(new SerializableRunnable() {
public void run() {
getCache().close();
}
});
}
}
private void setQueryVerbose(final boolean value, VM... vms) {
for (VM vm : vms) {
vm.invoke(new SerializableRunnable() {
public void run() {
DefaultQuery.QUERY_VERBOSE = value;
}
});
}
}
private class TestObject implements Serializable, Comparable {
@Override
public int compareTo(Object o) {
if (o instanceof TestObject) {
return score.compareTo(((TestObject) o).score);
}
return 1;
}
public Double score;
public TestObject(double score) {
this.score = score;
}
}
public interface PdxAssetFactory extends Serializable {
PdxAsset getAsset(int i);
}
public static class PdxNotDeserializableAsset extends PdxAsset {
public int assetId;
public String document;
public Collection<String> references = new ArrayList<String>();
public PdxNotDeserializableAsset() {
throw new RuntimeException("Preventing Deserialization of Asset");
}
public PdxNotDeserializableAsset(final int assetId, final String document) {
super(assetId, document);
}
@Override
public void fromData(final PdxReader reader) {
throw new RuntimeException("Not allowing us to deserialize one of these");
}
}
public static class PdxAsset implements PdxSerializable {
public int assetId;
public String document;
public Collection<String> references = new ArrayList<String>();
public PdxAsset() {
}
public PdxAsset(final int assetId, final String document) {
this.assetId = assetId;
this.document = document;
references.add(document + "_1");
references.add(document + "_2");
references.add(document + "_3");
}
@Override
public void toData(final PdxWriter writer) {
writer.writeString("document", document);
writer.writeInt("assetId", assetId);
writer.writeObject("references", references);
}
@Override
public void fromData(final PdxReader reader) {
this.document = reader.readString("document");
this.assetId = reader.readInt("assetId");
this.references = (Collection<String>) reader.readObject("references");
}
}
public static class NotDeserializableAsset implements DataSerializable {
private int disallowedPid;
public NotDeserializableAsset() {
}
public NotDeserializableAsset(final int disallowedPid) {
this.disallowedPid = disallowedPid;
}
@Override
public void toData(final DataOutput out) throws IOException {
out.writeInt(disallowedPid);
}
@Override
public void fromData(final DataInput in) throws IOException, ClassNotFoundException {
disallowedPid = in.readInt();
if (disallowedPid == DUnitEnv.get().getPid()) {
throw new IOException("Cannot deserialize");
}
}
}
public class NestedKeywordObject implements Serializable {
public Object date;
public Object nonKeyword;
public NestedKeywordObject(Object object) {
this.date = object;
}
public NestedKeywordObject(Object keywordObject, Object nonKeywordObject) {
this.date = keywordObject;
this.nonKeyword = nonKeywordObject;
}
}
private class PRQueryTraceTestHook implements DefaultQuery.TestHook, Serializable {
private HashMap<String, Boolean> hooks = new HashMap<String, Boolean>();
public HashMap<String, Boolean> getHooks() {
return hooks;
}
@Override
public void doTestHook(int spot) {
}
@Override
public void doTestHook(String spot) {
hooks.put(spot, Boolean.TRUE);
}
}
}