diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/NanoTimer.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/NanoTimer.java index c27bf442d..423655ce2 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/NanoTimer.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/NanoTimer.java @@ -55,7 +55,7 @@ public final class NanoTimer { private static final NativeCalls nativeCall = NativeCalls.getInstance(); - public static final int CLOCKID_BEST; + public static int CLOCKID_BEST; public static boolean CLOCKID_USE_SYSNANOTIME; public final static String NATIVETIMER_TYPE_PROPERTY = @@ -64,6 +64,10 @@ public final class NanoTimer { public static int nativeTimerType; static { + init(); + } + + public static void init() { /* * currently _nanoTime(..) isn't implemented in gemfire lib. * for gemfirexd, its implemented only for Linux/Solaris as of now. diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/BucketRegion.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/BucketRegion.java index 7ff10014c..08da0b1a1 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/BucketRegion.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/BucketRegion.java @@ -72,6 +72,7 @@ import com.gemstone.gemfire.internal.cache.locks.LockingPolicy.ReadEntryUnderLock; import com.gemstone.gemfire.internal.cache.locks.ReentrantReadWriteWriteShareLock; import com.gemstone.gemfire.internal.cache.partitioned.*; +import com.gemstone.gemfire.internal.cache.store.SerializedDiskBuffer; import com.gemstone.gemfire.internal.cache.tier.sockets.CacheClientNotifier; import com.gemstone.gemfire.internal.cache.tier.sockets.ClientTombstoneMessage; import com.gemstone.gemfire.internal.cache.tier.sockets.ClientUpdateMessage; @@ -120,8 +121,11 @@ public class BucketRegion extends DistributedRegion implements Bucket { * in theRealMap. Sizes are tallied during put and remove operations. */ private final AtomicLongWithTerminalState bytesInMemory = - new AtomicLongWithTerminalState(); - + new AtomicLongWithTerminalState(); + /** + * Contains size in bytes of the direct byte buffers stored in memory. + */ + private final AtomicLong directBufferBytesInMemory = new AtomicLong(); private final AtomicLong inProgressSize = new AtomicLong(); public static final ReadEntryUnderLock READ_SER_VALUE = new ReadEntryUnderLock() { @@ -2760,6 +2764,7 @@ else if (GemFireCacheImpl.gfxdSystem()) { this.partitionedRegion.getPrStats().incDataStoreEntryCount(-sizeBeforeClear); prDs.updateMemoryStats(-oldMemValue); } + this.directBufferBytesInMemory.set(0); // explicitly clear overflow counters if no diskRegion is present // (for latter the counters are cleared by DiskRegion.statsClear) if (getDiskRegion() == null) { @@ -2978,7 +2983,8 @@ protected void closeCallbacksExceptListener() { } public long getSizeInMemory() { - return Math.max(this.bytesInMemory.get(), 0L); + return Math.max(this.bytesInMemory.get(), 0L) + + this.directBufferBytesInMemory.get(); } public long getInProgressSize() { @@ -2991,9 +2997,10 @@ public void updateInProgressSize(long delta) { public long getTotalBytes() { long result = this.bytesInMemory.get(); - if(result == BUCKET_DESTROYED) { + if (result == BUCKET_DESTROYED) { return 0; } + result += this.directBufferBytesInMemory.get(); result += getNumOverflowBytesOnDisk(); return result; } @@ -3100,6 +3107,19 @@ public void updateMemoryStats(final Object oldValue, final Object newValue) { int oldValueSize = calcMemSize(oldValue); int newValueSize = calcMemSize(newValue); updateBucketMemoryStats(newValueSize - oldValueSize); + + if (this.cache.getMemorySize() > 0) { + int directBufferDelta = 0; + if (oldValue instanceof SerializedDiskBuffer) { + directBufferDelta -= ((SerializedDiskBuffer)oldValue).getOffHeapSizeInBytes(); + } + if (newValue instanceof SerializedDiskBuffer) { + directBufferDelta += ((SerializedDiskBuffer)newValue).getOffHeapSizeInBytes(); + } + if (directBufferDelta != 0) { + this.directBufferBytesInMemory.getAndAdd(directBufferDelta); + } + } } } diff --git a/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/LauncherBase.java b/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/LauncherBase.java index e3d6ab829..14133ae9a 100644 --- a/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/LauncherBase.java +++ b/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/LauncherBase.java @@ -300,21 +300,22 @@ protected void setDefaultVMArgs(Map map, boolean hostData, if (maxHeapStr != null && maxHeapStr.equals(this.initialHeapSize)) { String criticalHeapStr = (String)map.get(CRITICAL_HEAP_PERCENTAGE); if (criticalHeapStr == null) { - // for larger heaps, keep critical as 95% and 90% for smaller ones; + // for larger heaps, keep critical as 95-99% and 90% for smaller ones; // also limit memory remaining beyond critical to 4GB double heapSize = ClientSharedUtils.parseMemorySize(maxHeapStr, 0L, 0); if (heapSize > (40.0 * 1024.0 * 1024.0 * 1024.0)) { - // calculate percent that will leave out at max 4GB - criticalPercent = (float)(100.0 * (1.0 - twoGB / heapSize)); - // don't exceed 98% - if (criticalPercent > 98.0f) criticalPercent = 98.0f; + // calculate percent that will leave out at max 1GB + criticalPercent = (float)(100.0 * (1.0 - oneGB / heapSize)); } else if (heapSize >= twoGB) { - criticalPercent = 95.0f; + // leave out max 200MB + criticalPercent = (float)(100.0 * (1.0 - (200.0 * 1024.0 * 1024.0) / heapSize)); } else { criticalPercent = 90.0f; } + // don't exceed 99% + if (criticalPercent > 99.0f) criticalPercent = 99.0f; map.put(CRITICAL_HEAP_PERCENTAGE, "-" + CRITICAL_HEAP_PERCENTAGE + - '=' + criticalPercent); + '=' + String.format("%.2f", criticalPercent)); } else { criticalPercent = Float.parseFloat(criticalHeapStr.substring( criticalHeapStr.indexOf('=') + 1).trim()); diff --git a/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/NativeCalls.java b/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/NativeCalls.java index 960309ccc..0193a26c4 100644 --- a/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/NativeCalls.java +++ b/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/NativeCalls.java @@ -501,6 +501,12 @@ public static interface RehashServerOnSIGHUP { public boolean loadNativeLibrary() { return false; } + + /** + * Try to reinitialize native timer if available. + */ + public void reInitNativeTimer() { + } /** * whether o/s supports high resolution clock or equivalent @@ -511,7 +517,7 @@ public boolean loadNativeLibrary() { public boolean isNativeTimerEnabled() { return false; } - + /** * This is fall back for jni based library implementation of NanoTimer which * is more efficient than current impl through jna. diff --git a/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/jna/LinuxNativeCalls.java b/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/jna/LinuxNativeCalls.java index 2ab35f446..c31f924e9 100644 --- a/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/jna/LinuxNativeCalls.java +++ b/gemfire-shared/src/main/java/com/gemstone/gemfire/internal/shared/jna/LinuxNativeCalls.java @@ -126,10 +126,18 @@ protected boolean isNoProtocolOptionCode(int errno) { private static boolean isJNATimerEnabled = false; public static class TimeSpec extends Structure { - public int tv_sec; - public int tv_nsec; + int tv_sec; + int tv_nsec; static { + init(); + } + + static void loadClass() { + // just to ensure class is loaded + } + + static void init() { try { Native.register("rt"); TimeSpec res = new TimeSpec(); @@ -146,10 +154,6 @@ public static class TimeSpec extends Structure { } } - static void init() { - // just invoke the static block - } - public static native int clock_getres(int clkId, TimeSpec time) throws LastErrorException; @@ -163,10 +167,18 @@ protected List getFieldOrder() { } public static class TimeSpec64 extends Structure { - public long tv_sec; - public long tv_nsec; + long tv_sec; + long tv_nsec; static { + init(); + } + + static void loadClass() { + // just to ensure class is loaded + } + + static void init() { try { Native.register("rt"); TimeSpec64 res = new TimeSpec64(); @@ -183,10 +195,6 @@ public static class TimeSpec64 extends Structure { } } - static void init() { - // just invoke the static block - } - public static native int clock_getres(int clkId, TimeSpec64 time) throws LastErrorException; @@ -207,13 +215,25 @@ public boolean loadNativeLibrary() { * {@inheritDoc} */ @Override - public boolean isNativeTimerEnabled() { - // initialize static blocks + public void reInitNativeTimer() { if (NativeCallsJNAImpl.is64BitPlatform) { TimeSpec64.init(); } else { TimeSpec.init(); } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isNativeTimerEnabled() { + // initialization already done in static blocks + if (NativeCallsJNAImpl.is64BitPlatform) { + TimeSpec64.loadClass(); + } else { + TimeSpec.loadClass(); + } return isJNATimerEnabled; } diff --git a/gemfirexd/core/src/main/java/com/pivotal/gemfirexd/internal/engine/ui/SnappyRegionStatsCollectorFunction.java b/gemfirexd/core/src/main/java/com/pivotal/gemfirexd/internal/engine/ui/SnappyRegionStatsCollectorFunction.java index 610214203..f66513222 100644 --- a/gemfirexd/core/src/main/java/com/pivotal/gemfirexd/internal/engine/ui/SnappyRegionStatsCollectorFunction.java +++ b/gemfirexd/core/src/main/java/com/pivotal/gemfirexd/internal/engine/ui/SnappyRegionStatsCollectorFunction.java @@ -228,7 +228,6 @@ private SnappyRegionStats collectDataFromBeanImpl(LocalRegion lr, RegionMXBean b PartitionedRegionDataStore datastore = pr.getDataStore(); long sizeInMemory = 0L; long sizeOfRegion = 0L; - long offHeapBytes = 0L; long entryOverhead = 0L; long entryCount = 0L; if (datastore != null) { @@ -247,14 +246,13 @@ private SnappyRegionStats collectDataFromBeanImpl(LocalRegion lr, RegionMXBean b sizeOfRegion += constantOverhead + br.getTotalBytes(); entryCount += br.entryCount(); } - offHeapBytes = pr.getPrStats().getOffHeapSizeInBytes(); } if (entryOverhead > 0) { entryOverhead *= entryCount; } - tableStats.setSizeInMemory(sizeInMemory + offHeapBytes + entryOverhead); - tableStats.setTotalSize(sizeOfRegion + offHeapBytes + entryOverhead); + tableStats.setSizeInMemory(sizeInMemory + entryOverhead); + tableStats.setTotalSize(sizeOfRegion + entryOverhead); tableStats.setSizeSpillToDisk(tableStats.getTotalSize() - tableStats.getSizeInMemory()); } return tableStats; diff --git a/gemfirexd/tools/src/test/java/com/pivotal/gemfirexd/TestUtil.java b/gemfirexd/tools/src/test/java/com/pivotal/gemfirexd/TestUtil.java index 27a8b28ba..1fc99b74f 100644 --- a/gemfirexd/tools/src/test/java/com/pivotal/gemfirexd/TestUtil.java +++ b/gemfirexd/tools/src/test/java/com/pivotal/gemfirexd/TestUtil.java @@ -56,8 +56,8 @@ import com.gemstone.gemfire.internal.cache.xmlcache.RegionCreation; import com.gemstone.gemfire.internal.shared.ClientSharedUtils; import com.gemstone.gemfire.internal.shared.NativeCalls; -import com.gemstone.gemfire.internal.shared.jna.OSType; import com.gemstone.gemfire.internal.shared.StringPrintWriter; +import com.gemstone.gemfire.internal.shared.jna.OSType; import com.pivotal.gemfirexd.internal.engine.GemFireXDQueryObserver; import com.pivotal.gemfirexd.internal.engine.GemFireXDQueryObserverAdapter; import com.pivotal.gemfirexd.internal.engine.GfxdConstants; @@ -2231,8 +2231,13 @@ public static Object getField(Class clazz, T instance, } public static void assertTimerLibraryLoaded() { - final OSType ostype = NativeCalls.getInstance().getOSType(); + NativeCalls nc = NativeCalls.getInstance(); + final OSType ostype = nc.getOSType(); if (ostype == OSType.LINUX) { + if (!NanoTimer.isJNINativeTimerEnabled()) { + NanoTimer.init(); + nc.reInitNativeTimer(); + } assertTrue("Couldn't initialize jni native timer for " + ostype, NanoTimer.isJNINativeTimerEnabled()); assertTrue("Couldn't initialize the native timer for " + ostype,