use of org.apache.geode.cache.query.internal.cq.CqQueryImpl.TestHook in project geode by apache.
the class CqDataUsingPoolDUnitTest method testEventsDuringQueryExecution.
/**
* Test for events created during the CQ query execution. When CQs are executed using
* executeWithInitialResults there may be possibility that the region changes during that time may
* not be reflected in the query result set thus making the query data and region data
* inconsistent.
*/
@Test
public void testEventsDuringQueryExecution() throws Exception {
final Host host = Host.getHost(0);
VM server = host.getVM(0);
final VM client = host.getVM(1);
final String cqName = "testEventsDuringQueryExecution_0";
cqDUnitTest.createServer(server);
final int port = server.invoke(() -> CqQueryUsingPoolDUnitTest.getCacheServerPort());
final String host0 = NetworkUtils.getServerHostName(server.getHost());
String poolName = "testEventsDuringQueryExecution";
cqDUnitTest.createPool(client, poolName, host0, port);
// create CQ.
cqDUnitTest.createCQ(client, poolName, cqName, cqDUnitTest.cqs[0]);
final int numObjects = 200;
final int totalObjects = 500;
// initialize Region.
server.invoke(new CacheSerializableRunnable("Update Region") {
@Override
public void run2() throws CacheException {
Region region = getCache().getRegion("/root/" + cqDUnitTest.regions[0]);
for (int i = 1; i <= numObjects; i++) {
Portfolio p = new Portfolio(i);
region.put("" + i, p);
}
}
});
// First set testhook in executeWithInitialResults so that queued events
// are not drained before we verify there number.
client.invoke(setTestHook());
// Execute CQ while update is in progress.
AsyncInvocation executeCq = client.invokeAsync(new CacheSerializableRunnable("Execute CQ AsyncInvoke") {
@Override
public void run2() throws CacheException {
QueryService cqService = getCache().getQueryService();
// Get CqQuery object.
CqQuery cq1 = cqService.getCq(cqName);
if (cq1 == null) {
fail("Failed to get CQ " + cqName);
}
SelectResults cqResults = null;
try {
cqResults = cq1.executeWithInitialResults();
} catch (Exception ex) {
Assert.fail("CQ execution failed", ex);
}
// Check num of events received during executeWithInitialResults.
final TestHook testHook = CqQueryImpl.testHook;
Wait.waitForCriterion(new WaitCriterion() {
@Override
public boolean done() {
return testHook.numQueuedEvents() > 0;
}
@Override
public String description() {
return "No queued events found.";
}
}, 3000, 5, true);
getCache().getLogger().fine("Queued Events Size" + testHook.numQueuedEvents());
// Make sure CQEvents are queued during execute with initial results.
CqQueryTestListener cqListener = (CqQueryTestListener) cq1.getCqAttributes().getCqListener();
// Wait for the last key to arrive.
cqListener.waitForCreated("" + totalObjects);
// Check if the events from CqListener are in order.
int oldId = 0;
for (Object cqEvent : cqListener.events.toArray()) {
int newId = new Integer(cqEvent.toString()).intValue();
if (oldId > newId) {
fail("Queued events for CQ Listener during execution with " + "Initial results is not in the order in which they are created.");
}
oldId = newId;
}
// Check if all the IDs are present as part of Select Results and CQ Events.
HashSet ids = new HashSet(cqListener.events);
for (Object o : cqResults.asList()) {
Struct s = (Struct) o;
ids.add(s.get("key"));
}
HashSet missingIds = new HashSet();
String key = "";
for (int i = 1; i <= totalObjects; i++) {
key = "" + i;
if (!(ids.contains(key))) {
missingIds.add(key);
}
}
if (!missingIds.isEmpty()) {
fail("Missing Keys in either ResultSet or the Cq Event list. " + " Missing keys : [size : " + missingIds.size() + "]" + missingIds + " Ids in ResultSet and CQ Events :" + ids);
}
}
});
// Keep updating region (async invocation).
server.invoke(new CacheSerializableRunnable("Update Region") {
@Override
public void run2() throws CacheException {
Wait.pause(200);
client.invoke(new CacheSerializableRunnable("Releasing the latch") {
@Override
public void run2() throws CacheException {
// Now release the testhook so that CQListener can proceed.
final TestHook testHook = CqQueryImpl.testHook;
testHook.ready();
}
});
Region region = getCache().getRegion("/root/" + cqDUnitTest.regions[0]);
for (int i = numObjects + 1; i <= totalObjects; i++) {
Portfolio p = new Portfolio(i);
region.put("" + i, p);
}
}
});
// Close.
cqDUnitTest.closeClient(client);
cqDUnitTest.closeServer(server);
}
use of org.apache.geode.cache.query.internal.cq.CqQueryImpl.TestHook in project geode by apache.
the class CqDataUsingPoolDUnitTest method setTestHook.
public CacheSerializableRunnable setTestHook() {
SerializableRunnable sr = new CacheSerializableRunnable("TestHook") {
@Override
public void run2() {
class CqQueryTestHook implements CqQueryImpl.TestHook {
CountDownLatch latch = new CountDownLatch(1);
private int numEvents = 0;
Cache cache = GemFireCacheImpl.getInstance();
@Override
public void pauseUntilReady() {
try {
cache.getLogger().fine("CqQueryTestHook: Going to wait on latch until ready is called.");
if (!latch.await(10, TimeUnit.SECONDS)) {
fail("query was never unlatched");
}
} catch (Exception e) {
fail("interrupted", e);
}
}
@Override
public void ready() {
latch.countDown();
cache.getLogger().fine("CqQueryTestHook: The latch has been released.");
}
@Override
public int numQueuedEvents() {
return numEvents;
}
@Override
public void setEventCount(int count) {
cache.getLogger().fine("CqQueryTestHook: Setting numEVents to: " + count);
numEvents = count;
}
}
;
CqQueryImpl.testHook = new CqQueryTestHook();
}
};
return (CacheSerializableRunnable) sr;
}
Aggregations