Return-Path: X-Original-To: apmail-geode-commits-archive@minotaur.apache.org Delivered-To: apmail-geode-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id F0E2018ECF for ; Thu, 21 Jan 2016 22:14:42 +0000 (UTC) Received: (qmail 71548 invoked by uid 500); 21 Jan 2016 22:14:42 -0000 Delivered-To: apmail-geode-commits-archive@geode.apache.org Received: (qmail 71519 invoked by uid 500); 21 Jan 2016 22:14:42 -0000 Mailing-List: contact commits-help@geode.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.incubator.apache.org Delivered-To: mailing list commits@geode.incubator.apache.org Received: (qmail 71510 invoked by uid 99); 21 Jan 2016 22:14:42 -0000 Received: from Unknown (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 21 Jan 2016 22:14:42 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 661A4C1970 for ; Thu, 21 Jan 2016 22:14:42 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.78 X-Spam-Level: * X-Spam-Status: No, score=1.78 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-east.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id xh7ReMZ3BZa2 for ; Thu, 21 Jan 2016 22:14:34 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with SMTP id A278043EEE for ; Thu, 21 Jan 2016 22:14:33 +0000 (UTC) Received: (qmail 66704 invoked by uid 99); 21 Jan 2016 22:14:33 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 21 Jan 2016 22:14:33 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id EB7E3DFF94; Thu, 21 Jan 2016 22:14:32 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dschneider@apache.org To: commits@geode.incubator.apache.org Message-Id: <78b699545613457db1c77f253a5d65cc@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: incubator-geode git commit: GEODE-814: unit test DisconnectingOutOfOfHeapMemoryListener Date: Thu, 21 Jan 2016 22:14:32 +0000 (UTC) Repository: incubator-geode Updated Branches: refs/heads/develop 71eb357c2 -> 192c1ee10 GEODE-814: unit test DisconnectingOutOfOfHeapMemoryListener Unit test has been added. InternalDistributedSystem is no longer final so that unit tests can mock it. The reason it was made final was because in an older version of the product this class did license checking and we wanted to prevent it from being subclassed. But now that it no longer does a license check the final was not needed. Also the code coverage of OffHeapStorage was improved. Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/192c1ee1 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/192c1ee1 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/192c1ee1 Branch: refs/heads/develop Commit: 192c1ee1017773550ee328bcf49807e6cd967643 Parents: 71eb357 Author: Darrel Schneider Authored: Wed Jan 20 15:26:58 2016 -0800 Committer: Darrel Schneider Committed: Thu Jan 21 14:07:14 2016 -0800 ---------------------------------------------------------------------- .../internal/InternalDistributedSystem.java | 2 +- ...DisconnectingOutOfOffHeapMemoryListener.java | 77 ++++++++++++++ .../internal/offheap/OffHeapStorage.java | 52 ---------- ...tingOutOfOffHeapMemoryListenerJUnitTest.java | 100 +++++++++++++++++++ .../offheap/OffHeapStorageJUnitTest.java | 34 +++++-- 5 files changed, 206 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/192c1ee1/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java index 8f604b4..087407a 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/InternalDistributedSystem.java @@ -115,7 +115,7 @@ import com.gemstone.gemfire.security.GemFireSecurityException; * @since 3.0 * */ -public final class InternalDistributedSystem +public class InternalDistributedSystem extends DistributedSystem implements OsStatisticsFactory, StatisticsManager { http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/192c1ee1/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListener.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListener.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListener.java new file mode 100644 index 0000000..d9f85e8 --- /dev/null +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListener.java @@ -0,0 +1,77 @@ +/* + * 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 com.gemstone.gemfire.internal.offheap; + +import com.gemstone.gemfire.OutOfOffHeapMemoryException; +import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; + +/** + * Used to asynchronously disconnect an InternalDistributedSystem + * when we run out of off-heap memory. + * If the STAY_CONNECTED_ON_OUTOFOFFHEAPMEMORY_PROPERTY sys prop + * is set to true then this listener will not disconnect. + */ +class DisconnectingOutOfOffHeapMemoryListener implements OutOfOffHeapMemoryListener { + private final Object lock = new Object(); + private InternalDistributedSystem ids; + + DisconnectingOutOfOffHeapMemoryListener(InternalDistributedSystem ids) { + this.ids = ids; + } + + public void close() { + synchronized (lock) { + this.ids = null; // set null to prevent memory leak after closure! + } + } + + @Override + public void outOfOffHeapMemory(final OutOfOffHeapMemoryException cause) { + synchronized (lock) { + if (this.ids == null) { + return; + } + if (Boolean.getBoolean(OffHeapStorage.STAY_CONNECTED_ON_OUTOFOFFHEAPMEMORY_PROPERTY)) { + return; + } + + final InternalDistributedSystem dsToDisconnect = this.ids; + this.ids = null; // set null to prevent memory leak after closure! + + if (dsToDisconnect.getDistributionManager().getRootCause() == null) { + dsToDisconnect.getDistributionManager().setRootCause(cause); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + dsToDisconnect.getLogWriter().info("OffHeapStorage about to invoke disconnect on " + dsToDisconnect); + dsToDisconnect.disconnect(cause.getMessage(), cause, false); + } + }; + + // invoking disconnect is async because caller may be a DM pool thread which will block until DM shutdown times out + + //LogWriterImpl.LoggingThreadGroup group = LogWriterImpl.createThreadGroup("MemScale Threads", ids.getLogWriterI18n()); + String name = this.getClass().getSimpleName()+"@"+this.hashCode()+" Handle OutOfOffHeapMemoryException Thread"; + //Thread thread = new Thread(group, runnable, name); + Thread thread = new Thread(runnable, name); + thread.setDaemon(true); + thread.start(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/192c1ee1/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapStorage.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapStorage.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapStorage.java index c950134..bb5cdeb 100755 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapStorage.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/offheap/OffHeapStorage.java @@ -19,7 +19,6 @@ package com.gemstone.gemfire.internal.offheap; import java.lang.reflect.Method; import com.gemstone.gemfire.LogWriter; -import com.gemstone.gemfire.OutOfOffHeapMemoryException; import com.gemstone.gemfire.StatisticDescriptor; import com.gemstone.gemfire.Statistics; import com.gemstone.gemfire.StatisticsFactory; @@ -392,55 +391,4 @@ public class OffHeapStorage implements OffHeapMemoryStats { private void setFreeMemory(long value) { this.stats.setLong(freeMemoryId, value); } - - static class DisconnectingOutOfOffHeapMemoryListener implements OutOfOffHeapMemoryListener { - private final Object lock = new Object(); - private InternalDistributedSystem ids; - - DisconnectingOutOfOffHeapMemoryListener(InternalDistributedSystem ids) { - this.ids = ids; - } - - public void close() { - synchronized (lock) { - this.ids = null; // set null to prevent memory leak after closure! - } - } - - @Override - public void outOfOffHeapMemory(final OutOfOffHeapMemoryException cause) { - synchronized (lock) { - if (this.ids == null) { - return; - } - if (Boolean.getBoolean(STAY_CONNECTED_ON_OUTOFOFFHEAPMEMORY_PROPERTY)) { - return; - } - - final InternalDistributedSystem dsToDisconnect = this.ids; - this.ids = null; // set null to prevent memory leak after closure! - - if (dsToDisconnect.getDistributionManager().getRootCause() == null) { - dsToDisconnect.getDistributionManager().setRootCause(cause); - } - - Runnable runnable = new Runnable() { - @Override - public void run() { - dsToDisconnect.getLogWriter().info("OffHeapStorage about to invoke disconnect on " + dsToDisconnect); - dsToDisconnect.disconnect(cause.getMessage(), cause, false); - } - }; - - // invoking disconnect is async because caller may be a DM pool thread which will block until DM shutdown times out - - //LogWriterImpl.LoggingThreadGroup group = LogWriterImpl.createThreadGroup("MemScale Threads", ids.getLogWriterI18n()); - String name = this.getClass().getSimpleName()+"@"+this.hashCode()+" Handle OutOfOffHeapMemoryException Thread"; - //Thread thread = new Thread(group, runnable, name); - Thread thread = new Thread(runnable, name); - thread.setDaemon(true); - thread.start(); - } - } - } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/192c1ee1/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListenerJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListenerJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListenerJUnitTest.java new file mode 100644 index 0000000..671a2b5 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/DisconnectingOutOfOffHeapMemoryListenerJUnitTest.java @@ -0,0 +1,100 @@ +/* + * 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 com.gemstone.gemfire.internal.offheap; + +import static org.mockito.Mockito.*; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.LogWriter; +import com.gemstone.gemfire.OutOfOffHeapMemoryException; +import com.gemstone.gemfire.distributed.internal.DM; +import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; +import com.gemstone.gemfire.test.junit.categories.UnitTest; + +@Category(UnitTest.class) +public class DisconnectingOutOfOffHeapMemoryListenerJUnitTest { + @Rule + public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); + + private final InternalDistributedSystem ids = mock(InternalDistributedSystem.class); + private final OutOfOffHeapMemoryException ex = new OutOfOffHeapMemoryException(); + private final LogWriter lw = mock(LogWriter.class); + private final DM dm = mock(DM.class); + + @Before + public void setUp() throws Exception { + when(ids.getLogWriter()).thenReturn(lw); + when(ids.getDistributionManager()).thenReturn(dm); + } + + @Test + public void constructWithNullSupportsClose() { + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(null); + listener.close(); + } + + @Test + public void constructWithNullSupportsOutOfOffHeapMemory() { + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(null); + listener.outOfOffHeapMemory(null); + } + + @Test + public void disconnectNotCalledWhenSysPropIsSet() { + System.setProperty(OffHeapStorage.STAY_CONNECTED_ON_OUTOFOFFHEAPMEMORY_PROPERTY, "true"); + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(ids); + listener.outOfOffHeapMemory(ex); + verify(ids, never()).disconnect(ex.getMessage(), ex, false); + } + + @Test + public void disconnectNotCalledWhenListenerClosed() { + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(ids); + listener.close(); + listener.outOfOffHeapMemory(ex); + verify(ids, never()).disconnect(ex.getMessage(), ex, false); + } + + @Test + public void setRootCauseCalledWhenGetRootCauseReturnsNull() { + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(ids); + when(dm.getRootCause()).thenReturn(null); + listener.outOfOffHeapMemory(ex); + verify(dm).setRootCause(ex); + } + @Test + public void setRootCauseNotCalledWhenGetRootCauseReturnsNonNull() { + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(ids); + when(dm.getRootCause()).thenReturn(ex); + listener.outOfOffHeapMemory(ex); + verify(dm, never()).setRootCause(ex); + } + + @Test + public void disconnectCalledAsyncAfterCallingOutOfOffHeapMemory() { + DisconnectingOutOfOffHeapMemoryListener listener = new DisconnectingOutOfOffHeapMemoryListener(ids); + listener.outOfOffHeapMemory(ex); + verify(ids, timeout(5000).atLeastOnce()).disconnect(ex.getMessage(), ex, false); + verify(lw).info("OffHeapStorage about to invoke disconnect on " + ids); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/192c1ee1/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OffHeapStorageJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OffHeapStorageJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OffHeapStorageJUnitTest.java index d31daef..f0f0461 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OffHeapStorageJUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OffHeapStorageJUnitTest.java @@ -17,6 +17,7 @@ package com.gemstone.gemfire.internal.offheap; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.*; @@ -32,6 +33,7 @@ import com.gemstone.gemfire.OutOfOffHeapMemoryException; import com.gemstone.gemfire.StatisticsFactory; import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.distributed.internal.DistributionStats; +import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; import com.gemstone.gemfire.distributed.internal.InternalLocator; import com.gemstone.gemfire.internal.LocalStatisticsFactory; import com.gemstone.gemfire.test.junit.categories.UnitTest; @@ -118,30 +120,50 @@ public class OffHeapStorageJUnitTest { } } @Test - public void testCreateOffHeapStorage() { + public void createOffHeapStorageReturnsNullIfForceLocator() { System.setProperty(InternalLocator.FORCE_LOCATOR_DM_TYPE, "true"); - try { - assertEquals(null, OffHeapStorage.createOffHeapStorage(null, null, 0, null)); - } finally { - System.clearProperty(InternalLocator.FORCE_LOCATOR_DM_TYPE); - } + assertEquals(null, OffHeapStorage.createOffHeapStorage(null, null, 1, null)); + } + @Test + public void createOffHeapStorageReturnsNullIfMemorySizeIsZero() { + assertEquals(null, OffHeapStorage.createOffHeapStorage(null, null, 0, null)); + } + @Test + public void exceptionIfSlabCountTooSmall() { StatisticsFactory statsFactory = mock(StatisticsFactory.class); try { OffHeapStorage.createOffHeapStorage(null, statsFactory, OffHeapStorage.MIN_SLAB_SIZE-1, null); } catch (IllegalArgumentException expected) { expected.getMessage().equals("The amount of off heap memory must be at least " + OffHeapStorage.MIN_SLAB_SIZE + " but it was set to " + (OffHeapStorage.MIN_SLAB_SIZE-1)); } + } + @Test + public void exceptionIfDistributedSystemNull() { + StatisticsFactory statsFactory = mock(StatisticsFactory.class); try { OffHeapStorage.createOffHeapStorage(null, statsFactory, OffHeapStorage.MIN_SLAB_SIZE, (DistributedSystem)null); } catch (IllegalArgumentException expected) { expected.getMessage().equals("InternalDistributedSystem is null"); } + } + + @Test + public void createOffHeapStorageWorks() { + StatisticsFactory localStatsFactory = new LocalStatisticsFactory(null); + InternalDistributedSystem ids = mock(InternalDistributedSystem.class); + MemoryAllocator ma = OffHeapStorage.createOffHeapStorage(null, localStatsFactory, OffHeapStorage.MIN_SLAB_SIZE, ids); + System.setProperty(SimpleMemoryAllocatorImpl.FREE_OFF_HEAP_MEMORY_PROPERTY, "true"); + ma.close(); + } + @Test + public void testCreateOffHeapStorage() { StatisticsFactory localStatsFactory = new LocalStatisticsFactory(null); OutOfOffHeapMemoryListener ooohml = mock(OutOfOffHeapMemoryListener.class); MemoryAllocator ma = OffHeapStorage.basicCreateOffHeapStorage(null, localStatsFactory, 1024*1024, ooohml); try { OffHeapMemoryStats stats = ma.getStats(); + assertNotNull(stats.getStats()); assertEquals(1024*1024, stats.getFreeMemory()); assertEquals(1024*1024, stats.getMaxMemory()); assertEquals(0, stats.getUsedMemory());