Skip to content

Commit ced50b0

Browse files
committed
Merge branch 'cassandra-4.1' into cassandra-5.0
2 parents d17e6d1 + 73648c8 commit ced50b0

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Merged from 4.1:
66
* ReadCommandController should close fast to avoid deadlock when building secondary index (CASSANDRA-19564)
77
Merged from 4.0:
8+
* Backport fix to nodetool gcstats output for direct memory (CASSANDRA-21037)
89
* ArrayIndexOutOfBoundsException with repaired data tracking and counters (CASSANDRA-20871)
910
* Fix cleanup of old incremental repair sessions in case of owned token range changes or a table deleting (CASSANDRA-20877)
1011
* Fix memory leak in BufferPoolAllocator when a capacity needs to be extended (CASSANDRA-20753)

src/java/org/apache/cassandra/service/GCInspector.java

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.HashMap;
2727
import java.util.Map;
2828
import java.util.concurrent.TimeUnit;
29+
import java.util.concurrent.atomic.AtomicLong;
2930
import java.util.concurrent.atomic.AtomicReference;
3031

3132
import javax.management.MBeanServer;
@@ -56,27 +57,27 @@ public class GCInspector implements NotificationListener, GCInspectorMXBean
5657

5758
/*
5859
* The field from java.nio.Bits that tracks the total number of allocated
59-
* bytes of direct memory requires via ByteBuffer.allocateDirect that have not been GCed.
60+
* bytes of direct memory requested via ByteBuffer.allocateDirect that have not been GCed.
6061
*/
6162
final static Field BITS_TOTAL_CAPACITY;
6263

63-
6464
static
6565
{
66-
Field temp = null;
66+
Class<?> bitsClass = null;
67+
6768
try
6869
{
69-
Class<?> bitsClass = Class.forName("java.nio.Bits");
70-
Field f = bitsClass.getDeclaredField("TOTAL_CAPACITY");
71-
f.setAccessible(true);
72-
temp = f;
70+
bitsClass = Class.forName("java.nio.Bits");
7371
}
7472
catch (Throwable t)
7573
{
76-
logger.debug("Error accessing field of java.nio.Bits", t);
77-
//Don't care, will just return the dummy value -1 if we can't get at the field in this JVM
74+
logger.debug("Error returning class of java.nio.Bits", t);
7875
}
79-
BITS_TOTAL_CAPACITY = temp;
76+
77+
if (bitsClass != null)
78+
BITS_TOTAL_CAPACITY = getField(bitsClass, "TOTAL_CAPACITY");
79+
else
80+
BITS_TOTAL_CAPACITY = null;
8081
}
8182

8283
static final class State
@@ -303,28 +304,56 @@ public State getTotalSinceLastCheck()
303304
public double[] getAndResetStats()
304305
{
305306
State state = getTotalSinceLastCheck();
306-
double[] r = new double[7];
307+
double[] r = new double[9];
307308
r[0] = TimeUnit.NANOSECONDS.toMillis(nanoTime() - state.startNanos);
308309
r[1] = state.maxRealTimeElapsed;
309310
r[2] = state.totalRealTimeElapsed;
310311
r[3] = state.sumSquaresRealTimeElapsed;
311312
r[4] = state.totalBytesReclaimed;
312313
r[5] = state.count;
313-
r[6] = getAllocatedDirectMemory();
314+
r[6] = getTotalDirectMemory();
314315

315316
return r;
316317
}
317318

318-
private static long getAllocatedDirectMemory()
319+
private static long getTotalDirectMemory()
320+
{
321+
return getFieldValue(BITS_TOTAL_CAPACITY, true);
322+
}
323+
324+
private static Field getField(Class<?> clazz, String fieldName)
325+
{
326+
try
327+
{
328+
Field field = clazz.getDeclaredField(fieldName);
329+
field.setAccessible(true);
330+
return field;
331+
}
332+
catch (Throwable t)
333+
{
334+
logger.trace("Error accessing field {} of {}", fieldName, clazz.getName(), t);
335+
// Return null to indicate failure
336+
return null;
337+
}
338+
}
339+
340+
/**
341+
* Retrieves the value of a Field, handling both regular long fields and AtomicLong fields.
342+
*
343+
* @param field the Field to retrieve the value from
344+
* @param isAtomicLong true if the field is an AtomicLong, false if it's a regular long
345+
* @return the field value, or -1 if retrieval fails or field is null.
346+
*/
347+
private static long getFieldValue(Field field, boolean isAtomicLong)
319348
{
320-
if (BITS_TOTAL_CAPACITY == null) return -1;
349+
if (field == null) return -1;
321350
try
322351
{
323-
return BITS_TOTAL_CAPACITY.getLong(null);
352+
return isAtomicLong ? ((AtomicLong) field.get(null)).get() : field.getLong(null);
324353
}
325354
catch (Throwable t)
326355
{
327-
logger.trace("Error accessing field of java.nio.Bits", t);
356+
logger.trace("Error accessing field value of {}", field.getName(), t);
328357
//Don't care how or why we failed to get the value in this JVM. Return -1 to indicate failure
329358
return -1;
330359
}

0 commit comments

Comments
 (0)