/* * 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.wan.misc; import static org.junit.Assert.*; import java.util.Set; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.admin.AdminDistributedSystemFactory; import org.apache.geode.admin.AdminException; import org.apache.geode.admin.DistributedSystemConfig; import org.apache.geode.admin.internal.AdminDistributedSystemImpl; import org.apache.geode.cache.Region; import org.apache.geode.internal.cache.CacheObserverAdapter; import org.apache.geode.internal.cache.CacheObserverHolder; import org.apache.geode.internal.cache.LocalRegion; import org.apache.geode.internal.cache.wan.WANTestBase; import org.apache.geode.test.dunit.AsyncInvocation; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.LogWriterUtils; import org.apache.geode.test.dunit.SerializableRunnable; import org.apache.geode.test.dunit.VM; import org.apache.geode.test.dunit.Wait; import org.apache.geode.test.dunit.WaitCriterion; import org.apache.geode.test.junit.categories.DistributedTest; @Category(DistributedTest.class) public class ShutdownAllPersistentGatewaySenderDUnitTest extends WANTestBase { private static final long MAX_WAIT = 70000; private static final int NUM_KEYS = 1000; public ShutdownAllPersistentGatewaySenderDUnitTest() { super(); } @Override protected final void postSetUpWANTestBase() throws Exception { IgnoredException.addIgnoredException("Cache is being closed by ShutdownAll"); } private static final long serialVersionUID = 1L; @Test public void testGatewaySender() throws Exception { IgnoredException.addIgnoredException("Cache is shutting down"); Integer lnPort = (Integer) vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1)); Integer nyPort = (Integer) vm1.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort)); vm2.invoke(() -> WANTestBase.createCache(nyPort)); vm3.invoke(() -> WANTestBase.createCache(nyPort)); vm2.invoke(() -> WANTestBase.createReceiver()); vm2.invoke(() -> WANTestBase.createPersistentPartitionedRegion(getTestMethodName() + "_PR", "ln", 1, 100, isOffHeap())); vm3.invoke(() -> WANTestBase.createPersistentPartitionedRegion(getTestMethodName() + "_PR", "ln", 1, 100, isOffHeap())); vm4.invoke(() -> WANTestBase.createCache(lnPort)); vm4.invoke(() -> WANTestBase.createSender("ln", 2, false, 100, 400, false, false, null, true)); vm4.invoke(() -> WANTestBase.startSender("ln")); vm4.invoke(() -> WANTestBase.createPersistentPartitionedRegion(getTestMethodName() + "_PR", "ln", 1, 100, isOffHeap())); // set the CacheObserver to block the ShutdownAll SerializableRunnable waitAtShutdownAll = new SerializableRunnable() { @Override public void run() { LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER = true; CacheObserverHolder.setInstance(new CacheObserverAdapter() { @Override public void beforeShutdownAll() { final Region region = cache.getRegion(getTestMethodName() + "_PR"); Wait.waitForCriterion(new WaitCriterion() { @Override public boolean done() { return region.size() >= 2; } @Override public String description() { return "Wait for wan to have processed several events"; } }, 30000, 100, true); } }); } }; vm2.invoke(waitAtShutdownAll); vm3.invoke(waitAtShutdownAll); AsyncInvocation vm4_future = vm4.invokeAsync(() -> WANTestBase.doPuts(getTestMethodName() + "_PR", NUM_KEYS)); // ShutdownAll will be suspended at observer, so puts will continue AsyncInvocation future = shutDownAllMembers(vm2, 2, MAX_WAIT); future.join(MAX_WAIT); // now restart vm1 with gatewayHub LogWriterUtils.getLogWriter().info("restart in VM2"); vm2.invoke(() -> WANTestBase.createCache(nyPort)); vm3.invoke(() -> WANTestBase.createCache(nyPort)); AsyncInvocation vm3_future = vm3.invokeAsync(() -> WANTestBase .createPersistentPartitionedRegion(getTestMethodName() + "_PR", "ln", 1, 100, isOffHeap())); vm2.invoke(() -> WANTestBase.createPersistentPartitionedRegion(getTestMethodName() + "_PR", "ln", 1, 100, isOffHeap())); vm3_future.join(MAX_WAIT); vm3.invoke(new SerializableRunnable() { public void run() { final Region region = cache.getRegion(getTestMethodName() + "_PR"); cache.getLogger().info("vm1's region size before restart gatewayHub is " + region.size()); } }); vm2.invoke(() -> WANTestBase.createReceiver()); // wait for vm0 to finish its work vm4_future.join(MAX_WAIT); vm4.invoke(new SerializableRunnable() { public void run() { Region region = cache.getRegion(getTestMethodName() + "_PR"); assertEquals(NUM_KEYS, region.size()); } }); // verify the other side (vm1)'s entries received from gateway vm2.invoke(new SerializableRunnable() { public void run() { final Region region = cache.getRegion(getTestMethodName() + "_PR"); cache.getLogger().info("vm1's region size after restart gatewayHub is " + region.size()); Wait.waitForCriterion(new WaitCriterion() { public boolean done() { Object lastValue = region.get(NUM_KEYS - 1); if (lastValue != null && lastValue.equals(NUM_KEYS - 1)) { region.getCache().getLogger() .info("Last key has arrived, its value is " + lastValue + ", end of wait."); return true; } else return (region.size() == NUM_KEYS); } public String description() { return "Waiting for destination region to reach size: " + NUM_KEYS + ", current is " + region.size(); } }, MAX_WAIT, 100, true); assertEquals(NUM_KEYS, region.size()); } }); } private AsyncInvocation shutDownAllMembers(VM vm, final int expectedNumber, final long timeout) { AsyncInvocation future = vm.invokeAsync(new SerializableRunnable("Shutdown all the members") { public void run() { DistributedSystemConfig config; AdminDistributedSystemImpl adminDS = null; try { config = AdminDistributedSystemFactory .defineDistributedSystem(cache.getDistributedSystem(), ""); adminDS = (AdminDistributedSystemImpl) AdminDistributedSystemFactory .getDistributedSystem(config); adminDS.connect(); Set members = adminDS.shutDownAllMembers(timeout); int num = members == null ? 0 : members.size(); assertEquals(expectedNumber, num); } catch (AdminException e) { throw new RuntimeException(e); } finally { if (adminDS != null) { adminDS.disconnect(); } } } }); return future; } }