getUnreadableDirectories()
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 877a3c52eb..c5149cfcfa 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -20,7 +20,6 @@ package org.apache.cassandra.db;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
-import java.lang.management.ManagementFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
@@ -41,7 +40,6 @@ import com.google.common.util.concurrent.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.codahale.metrics.Snapshot;
import org.apache.cassandra.cache.*;
import org.apache.cassandra.concurrent.*;
import org.apache.cassandra.config.*;
@@ -72,7 +70,6 @@ import org.apache.cassandra.io.sstable.SSTableMultiWriter;
import org.apache.cassandra.io.sstable.format.*;
import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
import org.apache.cassandra.io.util.FileUtils;
-import org.apache.cassandra.io.util.RandomAccessReader;
import org.apache.cassandra.metrics.Sampler;
import org.apache.cassandra.metrics.Sampler.Sample;
import org.apache.cassandra.metrics.Sampler.SamplerType;
@@ -220,12 +217,33 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
private volatile boolean neverPurgeTombstones = false;
+ public static void shutdownFlushExecutor() throws InterruptedException
+ {
+ flushExecutor.shutdown();
+ flushExecutor.awaitTermination(60, TimeUnit.SECONDS);
+ }
+
+
public static void shutdownPostFlushExecutor() throws InterruptedException
{
postFlushExecutor.shutdown();
postFlushExecutor.awaitTermination(60, TimeUnit.SECONDS);
}
+ public static void shutdownReclaimExecutor() throws InterruptedException
+ {
+ reclaimExecutor.shutdown();
+ reclaimExecutor.awaitTermination(60, TimeUnit.SECONDS);
+ }
+
+ public static void shutdownPerDiskFlushExecutors() throws InterruptedException
+ {
+ for (ExecutorService executorService : perDiskflushExecutors)
+ executorService.shutdown();
+ for (ExecutorService executorService : perDiskflushExecutors)
+ executorService.awaitTermination(60, TimeUnit.SECONDS);
+ }
+
public void reload()
{
// metadata object has been mutated directly. make all the members jibe with new settings.
@@ -425,19 +443,10 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
oldMBeanName = String.format("org.apache.cassandra.db:type=%s,keyspace=%s,columnfamily=%s",
isIndex() ? "IndexColumnFamilies" : "ColumnFamilies",
keyspace.getName(), name);
- try
- {
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- ObjectName[] objectNames = {new ObjectName(mbeanName), new ObjectName(oldMBeanName)};
- for (ObjectName objectName : objectNames)
- {
- mbs.registerMBean(this, objectName);
- }
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+
+ String[] objectNames = {mbeanName, oldMBeanName};
+ for (String objectName : objectNames)
+ MBeanWrapper.instance.registerMBean(this, objectName);
}
else
{
@@ -548,14 +557,13 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
data.removeUnreadableSSTables(directory);
}
- void unregisterMBean() throws MalformedObjectNameException, InstanceNotFoundException, MBeanRegistrationException
+ void unregisterMBean() throws MalformedObjectNameException
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName[] objectNames = {new ObjectName(mbeanName), new ObjectName(oldMBeanName)};
for (ObjectName objectName : objectNames)
{
- if (mbs.isRegistered(objectName))
- mbs.unregisterMBean(objectName);
+ if (MBeanWrapper.instance.isRegistered(objectName))
+ MBeanWrapper.instance.unregisterMBean(objectName);
}
// unregister metrics
diff --git a/src/java/org/apache/cassandra/db/HintedHandOffManager.java b/src/java/org/apache/cassandra/db/HintedHandOffManager.java
index 3279acf88c..e26f658c58 100644
--- a/src/java/org/apache/cassandra/db/HintedHandOffManager.java
+++ b/src/java/org/apache/cassandra/db/HintedHandOffManager.java
@@ -17,13 +17,10 @@
*/
package org.apache.cassandra.db;
-import java.lang.management.ManagementFactory;
import java.util.List;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import org.apache.cassandra.hints.HintsService;
+import org.apache.cassandra.utils.MBeanWrapper;
/**
* A proxy class that implement the deprecated legacy HintedHandoffManagerMBean interface.
@@ -44,15 +41,7 @@ public final class HintedHandOffManager implements HintedHandOffManagerMBean
public void registerMBean()
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
}
public void deleteHintsForEndpoint(String host)
diff --git a/src/java/org/apache/cassandra/db/commitlog/CommitLog.java b/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
index 6537adcd3e..9d2a3695ca 100644
--- a/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
+++ b/src/java/org/apache/cassandra/db/commitlog/CommitLog.java
@@ -18,19 +18,15 @@
package org.apache.cassandra.db.commitlog;
import java.io.*;
-import java.lang.management.ManagementFactory;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.zip.CRC32;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.ParameterizedClass;
import org.apache.cassandra.db.*;
@@ -49,6 +45,7 @@ import org.apache.cassandra.security.EncryptionContext;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.JVMStabilityInspector;
+import org.apache.cassandra.utils.MBeanWrapper;
import static org.apache.cassandra.db.commitlog.CommitLogSegment.Allocation;
import static org.apache.cassandra.db.commitlog.CommitLogSegment.CommitLogSegmentFileComparator;
@@ -82,15 +79,7 @@ public class CommitLog implements CommitLogMBean
{
CommitLog log = new CommitLog(CommitLogArchiver.construct());
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(log, new ObjectName("org.apache.cassandra.db:type=Commitlog"));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(log, "org.apache.cassandra.db:type=Commitlog");
return log.start();
}
diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
index e56ed60716..bc5a883109 100644
--- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
+++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
@@ -19,14 +19,11 @@ package org.apache.cassandra.db.compaction;
import java.io.File;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.TabularData;
@@ -36,7 +33,6 @@ import com.google.common.collect.*;
import com.google.common.util.concurrent.*;
import org.apache.cassandra.locator.RangesAtEndpoint;
-import org.apache.cassandra.locator.Replica;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -119,15 +115,8 @@ public class CompactionManager implements CompactionManagerMBean
static
{
instance = new CompactionManager();
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(instance, new ObjectName(MBEAN_OBJECT_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+
+ MBeanWrapper.instance.registerMBean(instance, MBEAN_OBJECT_NAME);
}
private final CompactionExecutor executor = new CompactionExecutor();
@@ -232,6 +221,7 @@ public class CompactionManager implements CompactionManagerMBean
executor.shutdown();
validationExecutor.shutdown();
viewBuildExecutor.shutdown();
+ cacheCleanupExecutor.shutdown();
// interrupt compactions and validations
for (Holder compactionHolder : CompactionMetrics.getCompactions())
@@ -242,7 +232,7 @@ public class CompactionManager implements CompactionManagerMBean
// wait for tasks to terminate
// compaction tasks are interrupted above, so it shuold be fairy quick
// until not interrupted tasks to complete.
- for (ExecutorService exec : Arrays.asList(executor, validationExecutor, viewBuildExecutor))
+ for (ExecutorService exec : Arrays.asList(executor, validationExecutor, viewBuildExecutor, cacheCleanupExecutor))
{
try
{
diff --git a/src/java/org/apache/cassandra/diag/DiagnosticEventService.java b/src/java/org/apache/cassandra/diag/DiagnosticEventService.java
index 3f3de7c68d..5953a1d9cb 100644
--- a/src/java/org/apache/cassandra/diag/DiagnosticEventService.java
+++ b/src/java/org/apache/cassandra/diag/DiagnosticEventService.java
@@ -41,6 +41,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.utils.MBeanWrapper;
/**
* Service for publishing and consuming {@link DiagnosticEvent}s.
@@ -62,17 +63,7 @@ public final class DiagnosticEventService implements DiagnosticEventServiceMBean
private DiagnosticEventService()
{
-
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- ObjectName jmxObjectName = new ObjectName("org.apache.cassandra.diag:type=DiagnosticEventService");
- mbs.registerMBean(this, jmxObjectName);
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this,"org.apache.cassandra.diag:type=DiagnosticEventService");
// register broadcasters for JMX events
DiagnosticEventPersistence.start();
diff --git a/src/java/org/apache/cassandra/diag/LastEventIdBroadcaster.java b/src/java/org/apache/cassandra/diag/LastEventIdBroadcaster.java
index 9fe5c48533..8e991e6ec3 100644
--- a/src/java/org/apache/cassandra/diag/LastEventIdBroadcaster.java
+++ b/src/java/org/apache/cassandra/diag/LastEventIdBroadcaster.java
@@ -18,21 +18,19 @@
package org.apache.cassandra.diag;
-import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
-import javax.management.MBeanServer;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
-import javax.management.ObjectName;
import org.apache.cassandra.concurrent.ScheduledExecutors;
+import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.progress.jmx.JMXBroadcastExecutor;
/**
@@ -61,16 +59,8 @@ final class LastEventIdBroadcaster extends NotificationBroadcasterSupport implem
super(JMXBroadcastExecutor.executor);
summary.put("last_updated_at", 0L);
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- ObjectName jmxObjectName = new ObjectName("org.apache.cassandra.diag:type=LastEventIdBroadcaster");
- mbs.registerMBean(this, jmxObjectName);
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+
+ MBeanWrapper.instance.registerMBean(this, "org.apache.cassandra.diag:type=LastEventIdBroadcaster");
}
public static LastEventIdBroadcaster instance()
diff --git a/src/java/org/apache/cassandra/gms/FailureDetector.java b/src/java/org/apache/cassandra/gms/FailureDetector.java
index d7f73aba93..4a16f2a9e8 100644
--- a/src/java/org/apache/cassandra/gms/FailureDetector.java
+++ b/src/java/org/apache/cassandra/gms/FailureDetector.java
@@ -21,15 +21,12 @@ import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.nio.file.Path;
import java.io.*;
-import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.*;
@@ -42,6 +39,7 @@ import org.apache.cassandra.io.FSWriteError;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.utils.Clock;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.MBeanWrapper;
/**
* This FailureDetector is an implementation of the paper titled
@@ -88,15 +86,7 @@ public class FailureDetector implements IFailureDetector, FailureDetectorMBean
public FailureDetector()
{
// Register this instance with JMX
- try
- {
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
}
private static long getInitialValue()
diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java b/src/java/org/apache/cassandra/gms/Gossiper.java
index aedcb048c0..b789fe7875 100644
--- a/src/java/org/apache/cassandra/gms/Gossiper.java
+++ b/src/java/org/apache/cassandra/gms/Gossiper.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.gms;
-import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
import java.util.*;
import java.util.Map.Entry;
@@ -28,8 +27,6 @@ import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Suppliers;
@@ -41,6 +38,7 @@ import com.google.common.util.concurrent.Uninterruptibles;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.utils.CassandraVersion;
+import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -248,15 +246,7 @@ public class Gossiper implements IFailureDetectionEventListener, GossiperMBean
// Register this instance with JMX
if (registerJmx)
{
- try
- {
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
}
}
diff --git a/src/java/org/apache/cassandra/hints/HintsService.java b/src/java/org/apache/cassandra/hints/HintsService.java
index 73840d303f..1a352c246c 100644
--- a/src/java/org/apache/cassandra/hints/HintsService.java
+++ b/src/java/org/apache/cassandra/hints/HintsService.java
@@ -18,7 +18,6 @@
package org.apache.cassandra.hints;
import java.io.File;
-import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Collections;
@@ -29,9 +28,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.Collectors;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import org.apache.cassandra.db.Keyspace;
@@ -51,6 +47,7 @@ import org.apache.cassandra.metrics.StorageMetrics;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.service.StorageProxy;
import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.utils.MBeanWrapper;
import static com.google.common.collect.Iterables.transform;
@@ -138,15 +135,7 @@ public final class HintsService implements HintsServiceMBean
public void registerMBean()
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
}
/**
diff --git a/src/java/org/apache/cassandra/index/SecondaryIndexManager.java b/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
index c9a7cc6796..ec54a652a5 100644
--- a/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
+++ b/src/java/org/apache/cassandra/index/SecondaryIndexManager.java
@@ -1485,4 +1485,14 @@ public class SecondaryIndexManager implements IndexRegistry, INotificationConsum
false);
}
}
+
+ @VisibleForTesting
+ public static void shutdownExecutors() throws InterruptedException
+ {
+ ExecutorService[] executors = new ExecutorService[]{ asyncExecutor, blockingExecutor };
+ for (ExecutorService executor : executors)
+ executor.shutdown();
+ for (ExecutorService executor : executors)
+ executor.awaitTermination(60, TimeUnit.SECONDS);
+ }
}
diff --git a/src/java/org/apache/cassandra/io/sstable/IndexSummaryManager.java b/src/java/org/apache/cassandra/io/sstable/IndexSummaryManager.java
index b8d236a4a3..3630c2aff3 100644
--- a/src/java/org/apache/cassandra/io/sstable/IndexSummaryManager.java
+++ b/src/java/org/apache/cassandra/io/sstable/IndexSummaryManager.java
@@ -18,29 +18,32 @@
package org.apache.cassandra.io.sstable;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.*;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.concurrent.DebuggableScheduledThreadPoolExecutor;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.ColumnFamilyStore;
-import org.apache.cassandra.db.compaction.OperationType;
import org.apache.cassandra.db.Keyspace;
-import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
-import org.apache.cassandra.db.lifecycle.View;
-import org.apache.cassandra.db.lifecycle.SSTableSet;
import org.apache.cassandra.db.compaction.CompactionManager;
+import org.apache.cassandra.db.compaction.OperationType;
+import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
+import org.apache.cassandra.db.lifecycle.SSTableSet;
+import org.apache.cassandra.db.lifecycle.View;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.schema.TableId;
+import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.Pair;
import org.apache.cassandra.utils.WrappedRunnable;
@@ -65,16 +68,7 @@ public class IndexSummaryManager implements IndexSummaryManagerMBean
static
{
instance = new IndexSummaryManager();
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-
- try
- {
- mbs.registerMBean(instance, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(instance, MBEAN_NAME);
}
private IndexSummaryManager()
diff --git a/src/java/org/apache/cassandra/io/util/DataInputBuffer.java b/src/java/org/apache/cassandra/io/util/DataInputBuffer.java
index a68dcc25ff..9df9861cca 100644
--- a/src/java/org/apache/cassandra/io/util/DataInputBuffer.java
+++ b/src/java/org/apache/cassandra/io/util/DataInputBuffer.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.io.util;
-import java.io.IOException;
import java.nio.ByteBuffer;
/**
@@ -57,14 +56,17 @@ public class DataInputBuffer extends RebufferingInputStream
}
@Override
- protected void reBuffer() throws IOException
+ protected void reBuffer()
{
//nope, we don't rebuffer, we are done!
}
@Override
- public int available() throws IOException
+ public int available()
{
return buffer.remaining();
}
+
+ @Override
+ public void close() {}
}
diff --git a/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java b/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
index d35f1fb202..ddc8fba276 100644
--- a/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
+++ b/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
@@ -18,7 +18,6 @@
package org.apache.cassandra.locator;
-import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
@@ -28,8 +27,6 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.codahale.metrics.ExponentiallyDecayingReservoir;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import com.codahale.metrics.Snapshot;
import org.apache.cassandra.concurrent.ScheduledExecutors;
@@ -41,6 +38,7 @@ import org.apache.cassandra.gms.VersionedValue;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.MBeanWrapper;
/**
* A dynamic snitch that sorts endpoints by latency with an adapted phi failure detector
@@ -141,15 +139,7 @@ public class DynamicEndpointSnitch extends AbstractEndpointSnitch implements ILa
private void registerMBean()
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(this, new ObjectName(mbeanName));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, mbeanName);
}
public void close()
@@ -157,15 +147,7 @@ public class DynamicEndpointSnitch extends AbstractEndpointSnitch implements ILa
updateSchedular.cancel(false);
resetSchedular.cancel(false);
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.unregisterMBean(new ObjectName(mbeanName));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.unregisterMBean(mbeanName);
}
@Override
diff --git a/src/java/org/apache/cassandra/locator/EndpointSnitchInfo.java b/src/java/org/apache/cassandra/locator/EndpointSnitchInfo.java
index da90a79321..d836cd1806 100644
--- a/src/java/org/apache/cassandra/locator/EndpointSnitchInfo.java
+++ b/src/java/org/apache/cassandra/locator/EndpointSnitchInfo.java
@@ -17,28 +17,16 @@
*/
package org.apache.cassandra.locator;
-
-import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.MBeanWrapper;
public class EndpointSnitchInfo implements EndpointSnitchInfoMBean
{
public static void create()
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(new EndpointSnitchInfo(), new ObjectName("org.apache.cassandra.db:type=EndpointSnitchInfo"));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(new EndpointSnitchInfo(), "org.apache.cassandra.db:type=EndpointSnitchInfo");
}
public String getDatacenter(String host) throws UnknownHostException
diff --git a/src/java/org/apache/cassandra/metrics/CassandraMetricsRegistry.java b/src/java/org/apache/cassandra/metrics/CassandraMetricsRegistry.java
index 43d66093c0..74c3367eb2 100644
--- a/src/java/org/apache/cassandra/metrics/CassandraMetricsRegistry.java
+++ b/src/java/org/apache/cassandra/metrics/CassandraMetricsRegistry.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.metrics;
-import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
@@ -26,14 +25,14 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
-
-import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
-import com.codahale.metrics.*;
import com.google.common.annotations.VisibleForTesting;
+import com.codahale.metrics.*;
+import org.apache.cassandra.utils.MBeanWrapper;
+
/**
* Makes integrating 3.0 metrics API with 2.0.
*
@@ -45,7 +44,7 @@ public class CassandraMetricsRegistry extends MetricRegistry
public static final CassandraMetricsRegistry Metrics = new CassandraMetricsRegistry();
private final Map threadPoolMetrics = new ConcurrentHashMap<>();
- private final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ private final MBeanWrapper mBeanServer = MBeanWrapper.instance;
private CassandraMetricsRegistry()
{
@@ -159,11 +158,7 @@ public class CassandraMetricsRegistry extends MetricRegistry
{
boolean removed = remove(name.getMetricName());
- try
- {
- mBeanServer.unregisterMBean(name.getMBeanName());
- } catch (Exception ignore) {}
-
+ mBeanServer.unregisterMBean(name.getMBeanName(), MBeanWrapper.OnException.IGNORE);
return removed;
}
@@ -194,13 +189,8 @@ public class CassandraMetricsRegistry extends MetricRegistry
else
throw new IllegalArgumentException("Unknown metric type: " + metric.getClass());
- try
- {
- mBeanServer.registerMBean(mbean, name);
- }
- catch (Exception ignored)
- {
- }
+ if (!mBeanServer.isRegistered(name))
+ mBeanServer.registerMBean(mbean, name, MBeanWrapper.OnException.LOG);
}
private void registerAlias(MetricName existingName, MetricName aliasName)
@@ -213,10 +203,8 @@ public class CassandraMetricsRegistry extends MetricRegistry
private void removeAlias(MetricName name)
{
- try
- {
- mBeanServer.unregisterMBean(name.getMBeanName());
- } catch (Exception ignore) {}
+ if (mBeanServer.isRegistered(name.getMBeanName()))
+ MBeanWrapper.instance.unregisterMBean(name.getMBeanName(), MBeanWrapper.OnException.IGNORE);
}
/**
diff --git a/src/java/org/apache/cassandra/net/ForwardToContainer.java b/src/java/org/apache/cassandra/net/ForwardToContainer.java
index ac9e725fa0..b22eed6b9f 100644
--- a/src/java/org/apache/cassandra/net/ForwardToContainer.java
+++ b/src/java/org/apache/cassandra/net/ForwardToContainer.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.net;
+import java.io.Serializable;
import java.util.Collection;
import com.google.common.base.Preconditions;
@@ -28,7 +29,7 @@ import org.apache.cassandra.locator.InetAddressAndPort;
* Contains forward to information until it can be serialized as part of a message using a version
* specific serialization
*/
-public class ForwardToContainer
+public class ForwardToContainer implements Serializable
{
public final Collection targets;
public final int[] messageIds;
diff --git a/src/java/org/apache/cassandra/net/MessageIn.java b/src/java/org/apache/cassandra/net/MessageIn.java
index 1cd39f3370..c8f4bfcd26 100644
--- a/src/java/org/apache/cassandra/net/MessageIn.java
+++ b/src/java/org/apache/cassandra/net/MessageIn.java
@@ -49,12 +49,12 @@ public class MessageIn
public final int version;
public final long constructionTime;
- private MessageIn(InetAddressAndPort from,
- T payload,
- Map parameters,
- Verb verb,
- int version,
- long constructionTime)
+ public MessageIn(InetAddressAndPort from,
+ T payload,
+ Map parameters,
+ Verb verb,
+ int version,
+ long constructionTime)
{
this.from = from;
this.payload = payload;
diff --git a/src/java/org/apache/cassandra/net/MessagingService.java b/src/java/org/apache/cassandra/net/MessagingService.java
index c6e8496d5b..761e210e1f 100644
--- a/src/java/org/apache/cassandra/net/MessagingService.java
+++ b/src/java/org/apache/cassandra/net/MessagingService.java
@@ -19,7 +19,6 @@ package org.apache.cassandra.net;
import java.io.IOError;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
@@ -35,8 +34,6 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@@ -112,6 +109,7 @@ import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.BooleanSerializer;
import org.apache.cassandra.utils.ExpiringMap;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.NativeLibrary;
import org.apache.cassandra.utils.Pair;
import org.apache.cassandra.utils.StatusLogger;
@@ -464,6 +462,20 @@ public final class MessagingService implements MessagingServiceMBean
}
}
+ public static IVersionedSerializer> getVerbSerializer(Verb verb, int id)
+ {
+ IVersionedSerializer serializer = verbSerializers.get(verb);
+ if (serializer instanceof MessagingService.CallbackDeterminedSerializer)
+ {
+ CallbackInfo callback = MessagingService.instance().getRegisteredCallback(id);
+ if (callback == null)
+ return null;
+
+ serializer = callback.serializer;
+ }
+ return serializer;
+ }
+
/* Lookup table for registering message handlers based on the verb. */
private final Map verbHandlers;
@@ -618,15 +630,7 @@ public final class MessagingService implements MessagingServiceMBean
if (!testOnly)
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
}
}
diff --git a/src/java/org/apache/cassandra/net/async/ByteBufDataInputPlus.java b/src/java/org/apache/cassandra/net/async/ByteBufDataInputPlus.java
index 23e532c371..e0be7151b1 100644
--- a/src/java/org/apache/cassandra/net/async/ByteBufDataInputPlus.java
+++ b/src/java/org/apache/cassandra/net/async/ByteBufDataInputPlus.java
@@ -22,6 +22,8 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import org.apache.cassandra.io.util.DataInputPlus;
+import java.io.IOException;
+
public class ByteBufDataInputPlus extends ByteBufInputStream implements DataInputPlus
{
/**
@@ -40,4 +42,10 @@ public class ByteBufDataInputPlus extends ByteBufInputStream implements DataInpu
{
return buf;
}
+
+ @Override
+ public String readUTF() throws IOException
+ {
+ return DataInputStreamPlus.readUTF(this);
+ }
}
diff --git a/src/java/org/apache/cassandra/net/async/MessageInHandler.java b/src/java/org/apache/cassandra/net/async/MessageInHandler.java
index 0a194d479c..dafa993333 100644
--- a/src/java/org/apache/cassandra/net/async/MessageInHandler.java
+++ b/src/java/org/apache/cassandra/net/async/MessageInHandler.java
@@ -18,15 +18,17 @@
package org.apache.cassandra.net.async;
-import java.io.DataInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
+import java.util.function.BooleanSupplier;
import com.google.common.primitives.Ints;
+import org.apache.cassandra.io.IVersionedSerializer;
+import org.apache.cassandra.io.util.DataInputPlus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -102,7 +104,7 @@ public class MessageInHandler extends BaseMessageInHandler
{
if (in.readableBytes() < messageHeader.parameterLength)
return;
- readParameters(in, inputPlus, messageHeader.parameterLength, messageHeader.parameters);
+ readParameters(in, inputPlus, messagingVersion, messageHeader.parameterLength, messageHeader.parameters);
}
state = State.READ_PAYLOAD_SIZE;
// fall-through
@@ -134,17 +136,17 @@ public class MessageInHandler extends BaseMessageInHandler
}
}
- private void readParameters(ByteBuf in, ByteBufDataInputPlus inputPlus, int parameterLength, Map parameters) throws IOException
+ private static void readParameters(ByteBuf buf, DataInputPlus in, int messagingVersion, int parameterLength, Map parameters) throws IOException
{
// makes the assumption we have all the bytes required to read the headers
- final int endIndex = in.readerIndex() + parameterLength;
- while (in.readerIndex() < endIndex)
+ final int endIndex = buf.readerIndex() + parameterLength;
+ while (buf.readerIndex() < endIndex)
{
- String key = DataInputStream.readUTF(inputPlus);
+ String key = in.readUTF();
ParameterType parameterType = ParameterType.byName.get(key);
- long valueLength = VIntCoding.readUnsignedVInt(in);
+ long valueLength = in.readUnsignedVInt();
byte[] value = new byte[Ints.checkedCast(valueLength)];
- in.readBytes(value);
+ in.readFully(value);
try (DataInputBuffer buffer = new DataInputBuffer(value))
{
parameters.put(parameterType, parameterType.serializer.deserialize(buffer, messagingVersion));
@@ -152,6 +154,55 @@ public class MessageInHandler extends BaseMessageInHandler
}
}
+ private static void readParameters(BooleanSupplier isDone, DataInputPlus in, int messagingVersion, Map parameters) throws IOException
+ {
+ // makes the assumption we have all the bytes required to read the headers
+ while (!isDone.getAsBoolean())
+ {
+ String key = in.readUTF();
+ ParameterType parameterType = ParameterType.byName.get(key);
+ in.readUnsignedVInt();
+ parameters.put(parameterType, parameterType.serializer.deserialize(in, messagingVersion));
+ }
+ }
+
+ public static MessageIn> deserialize(DataInputPlus in, int id, int version, InetAddressAndPort from) throws IOException
+ {
+ if (version >= MessagingService.VERSION_40)
+ return deserialize40(in, id, version, from);
+ else
+ return MessageInHandlerPre40.deserializePre40(in, id, version, from);
+ }
+
+ private static MessageIn> deserialize40(DataInputPlus in, int id, int version, InetAddressAndPort from) throws IOException
+ {
+ MessagingService.Verb verb = MessagingService.Verb.fromId(in.readInt());
+
+ Map parameters = Collections.emptyMap();
+ int parameterLength = (int) in.readUnsignedVInt();
+ if (parameterLength != 0)
+ {
+ parameters = new EnumMap<>(ParameterType.class);
+ byte[] bytes = new byte[parameterLength];
+ in.readFully(bytes);
+ try (DataInputBuffer buffer = new DataInputBuffer(bytes))
+ {
+ readParameters(() -> buffer.available() == 0, buffer, version, parameters);
+ }
+ }
+
+ Object payload = null;
+ int payloadSize = (int) in.readUnsignedVInt();
+ if (payloadSize > 0)
+ {
+ IVersionedSerializer serializer = MessagingService.getVerbSerializer(verb, id);
+ if (serializer == null) in.skipBytesFully(payloadSize);
+ else payload = serializer.deserialize(in, version);
+ }
+
+ return new MessageIn<>(from, payload, parameters, verb, version, System.nanoTime());
+ }
+
@Override
MessageHeader getMessageHeader()
{
diff --git a/src/java/org/apache/cassandra/net/async/MessageInHandlerPre40.java b/src/java/org/apache/cassandra/net/async/MessageInHandlerPre40.java
index f5b6fc441c..6eeeea7dd2 100644
--- a/src/java/org/apache/cassandra/net/async/MessageInHandlerPre40.java
+++ b/src/java/org/apache/cassandra/net/async/MessageInHandlerPre40.java
@@ -25,8 +25,11 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
+import java.util.function.BooleanSupplier;
import com.google.common.annotations.VisibleForTesting;
+import org.apache.cassandra.io.IVersionedSerializer;
+import org.apache.cassandra.io.util.DataInputPlus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -155,10 +158,10 @@ public class MessageInHandlerPre40 extends BaseMessageInHandler
if (!canReadNextParam(in))
return false;
- String key = DataInputStream.readUTF(inputPlus);
+ String key = inputPlus.readUTF();
ParameterType parameterType = ParameterType.byName.get(key);
- byte[] value = new byte[in.readInt()];
- in.readBytes(value);
+ byte[] value = new byte[inputPlus.readInt()];
+ inputPlus.readFully(value);
try (DataInputBuffer buffer = new DataInputBuffer(value))
{
parameters.put(parameterType, parameterType.serializer.deserialize(buffer, messagingVersion));
@@ -168,6 +171,47 @@ public class MessageInHandlerPre40 extends BaseMessageInHandler
return true;
}
+ private static boolean readParameters(DataInputPlus in, int messagingVersion, int parameterCount, Map parameters) throws IOException
+ {
+ // makes the assumption that map.size() is a constant time function (HashMap.size() is)
+ while (parameters.size() < parameterCount)
+ {
+ String key = in.readUTF();
+ ParameterType parameterType = ParameterType.byName.get(key);
+ in.readInt();
+ parameters.put(parameterType, parameterType.serializer.deserialize(in, messagingVersion));
+ }
+
+ return true;
+ }
+
+ static MessageIn> deserializePre40(DataInputPlus in, int id, int version, InetAddressAndPort from) throws IOException
+ {
+ assert from.equals(CompactEndpointSerializationHelper.instance.deserialize(in, version));
+ MessagingService.Verb verb = MessagingService.Verb.fromId(in.readInt());
+
+ Map parameters = Collections.emptyMap();
+ int parameterCount = in.readInt();
+ if (parameterCount != 0)
+ {
+ parameters = new EnumMap<>(ParameterType.class);
+ readParameters(in, version, parameterCount, parameters);
+ }
+
+ Object payload = null;
+ int payloadSize = in.readInt();
+ if (payloadSize > 0)
+ {
+ IVersionedSerializer serializer = MessagingService.getVerbSerializer(verb, id);
+ if (serializer == null) in.skipBytesFully(payloadSize);
+ else payload = serializer.deserialize(in, version);
+ }
+
+ return new MessageIn<>(from, payload, parameters, verb, version, System.nanoTime());
+ }
+
+
+
/**
* Determine if we can read the next parameter from the {@link ByteBuf}. This method will *always* set the {@code in}
* readIndex back to where it was when this method was invoked.
diff --git a/src/java/org/apache/cassandra/net/async/NettyFactory.java b/src/java/org/apache/cassandra/net/async/NettyFactory.java
index 989e33c25e..2366722092 100644
--- a/src/java/org/apache/cassandra/net/async/NettyFactory.java
+++ b/src/java/org/apache/cassandra/net/async/NettyFactory.java
@@ -2,6 +2,7 @@ package org.apache.cassandra.net.async;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
import java.util.zip.Checksum;
import javax.annotation.Nullable;
@@ -384,12 +385,13 @@ public final class NettyFactory
}
}
- public void close()
+ public void close() throws InterruptedException
{
- acceptGroup.shutdownGracefully();
- outboundGroup.shutdownGracefully();
- inboundGroup.shutdownGracefully();
- streamingGroup.shutdownGracefully();
+ EventLoopGroup[] groups = new EventLoopGroup[] { acceptGroup, outboundGroup, inboundGroup, streamingGroup };
+ for (EventLoopGroup group : groups)
+ group.shutdownGracefully();
+ for (EventLoopGroup group : groups)
+ group.awaitTermination(60, TimeUnit.SECONDS);
}
static Lz4FrameEncoder createLz4Encoder(int protocolVersion)
diff --git a/src/java/org/apache/cassandra/schema/SchemaEvent.java b/src/java/org/apache/cassandra/schema/SchemaEvent.java
index e26cee5b45..00c8136766 100644
--- a/src/java/org/apache/cassandra/schema/SchemaEvent.java
+++ b/src/java/org/apache/cassandra/schema/SchemaEvent.java
@@ -29,13 +29,14 @@ import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.MapDifference;
import org.apache.cassandra.diag.DiagnosticEvent;
import org.apache.cassandra.utils.Pair;
-final class SchemaEvent extends DiagnosticEvent
+public final class SchemaEvent extends DiagnosticEvent
{
private final SchemaEventType type;
@@ -62,7 +63,7 @@ final class SchemaEvent extends DiagnosticEvent
@Nullable
private final MapDifference indexesDiff;
- enum SchemaEventType
+ public enum SchemaEventType
{
KS_METADATA_LOADED,
KS_METADATA_RELOADED,
diff --git a/src/java/org/apache/cassandra/service/ActiveRepairService.java b/src/java/org/apache/cassandra/service/ActiveRepairService.java
index b32f67e98e..1a54e751ec 100644
--- a/src/java/org/apache/cassandra/service/ActiveRepairService.java
+++ b/src/java/org/apache/cassandra/service/ActiveRepairService.java
@@ -18,15 +18,11 @@
package org.apache.cassandra.service;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import com.google.common.base.Preconditions;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@@ -78,6 +74,7 @@ import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.utils.CassandraVersion;
import org.apache.cassandra.utils.Clock;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.Pair;
import org.apache.cassandra.utils.UUIDGen;
@@ -169,15 +166,7 @@ public class ActiveRepairService implements IEndpointStateChangeSubscriber, IFai
.maximumSize(Long.getLong("cassandra.parent_repair_status_cache_size", 100_000))
.build();
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
}
public void start()
diff --git a/src/java/org/apache/cassandra/service/CacheService.java b/src/java/org/apache/cassandra/service/CacheService.java
index 479470cec2..5eeaf20814 100644
--- a/src/java/org/apache/cassandra/service/CacheService.java
+++ b/src/java/org/apache/cassandra/service/CacheService.java
@@ -18,7 +18,6 @@
package org.apache.cassandra.service;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
@@ -27,9 +26,6 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import com.google.common.util.concurrent.Futures;
import org.slf4j.Logger;
@@ -53,6 +49,7 @@ import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.Pair;
public class CacheService implements CacheServiceMBean
@@ -88,16 +85,7 @@ public class CacheService implements CacheServiceMBean
private CacheService()
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-
- try
- {
- mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ MBeanWrapper.instance.registerMBean(this, MBEAN_NAME);
keyCache = initKeyCache();
rowCache = initRowCache();
diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java
index f0b2dc1d8a..592419acde 100644
--- a/src/java/org/apache/cassandra/service/CassandraDaemon.java
+++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java
@@ -569,16 +569,7 @@ public class CassandraDaemon
{
applyConfig();
- try
- {
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- mbs.registerMBean(new StandardMBean(new NativeAccess(), NativeAccessMBean.class), new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- logger.error("error registering MBean {}", MBEAN_NAME, e);
- //Allow the server to start even if the bean can't be registered
- }
+ MBeanWrapper.instance.registerMBean(new StandardMBean(new NativeAccess(), NativeAccessMBean.class), MBEAN_NAME, MBeanWrapper.OnException.LOG);
if (FBUtilities.isWindows)
{
diff --git a/src/java/org/apache/cassandra/service/PendingRangeCalculatorService.java b/src/java/org/apache/cassandra/service/PendingRangeCalculatorService.java
index 7b6bd58ae5..a3f6b52323 100644
--- a/src/java/org/apache/cassandra/service/PendingRangeCalculatorService.java
+++ b/src/java/org/apache/cassandra/service/PendingRangeCalculatorService.java
@@ -30,6 +30,8 @@ import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
+import com.google.common.annotations.VisibleForTesting;
+
public class PendingRangeCalculatorService
{
public static final PendingRangeCalculatorService instance = new PendingRangeCalculatorService();
@@ -117,4 +119,11 @@ public class PendingRangeCalculatorService
{
StorageService.instance.getTokenMetadata().calculatePendingRanges(strategy, keyspaceName);
}
+
+ @VisibleForTesting
+ public void shutdownExecutor() throws InterruptedException
+ {
+ executor.shutdown();
+ executor.awaitTermination(60, TimeUnit.SECONDS);
+ }
}
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java
index 630dc5d5cb..439d8cf7bc 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -18,7 +18,6 @@
package org.apache.cassandra.service;
import java.io.File;
-import java.lang.management.ManagementFactory;
import java.nio.ByteBuffer;
import java.nio.file.Paths;
import java.util.*;
@@ -26,9 +25,6 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.cache.CacheLoader;
@@ -123,16 +119,7 @@ public class StorageProxy implements StorageProxyMBean
static
{
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- mbs.registerMBean(instance, new ObjectName(MBEAN_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
-
+ MBeanWrapper.instance.registerMBean(instance, MBEAN_NAME);
HintsService.instance.registerMBean();
HintedHandOffManager.instance.registerMBean();
diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java
index e7ca4bec0b..68dba938b0 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -231,7 +231,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
private final List lifecycleSubscribers = new CopyOnWriteArrayList<>();
- private final ObjectName jmxObjectName;
+ private final String jmxObjectName;
private Collection bootstrapTokens = null;
@@ -270,17 +270,9 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
// use dedicated executor for handling JMX notifications
super(JMXBroadcastExecutor.executor);
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try
- {
- jmxObjectName = new ObjectName("org.apache.cassandra.db:type=StorageService");
- mbs.registerMBean(this, jmxObjectName);
- mbs.registerMBean(StreamManager.instance, new ObjectName(StreamManager.OBJECT_NAME));
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ jmxObjectName = "org.apache.cassandra.db:type=StorageService";
+ MBeanWrapper.instance.registerMBean(this, jmxObjectName);
+ MBeanWrapper.instance.registerMBean(StreamManager.instance, StreamManager.OBJECT_NAME);
ReadCommandVerbHandler readHandler = new ReadCommandVerbHandler();
diff --git a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
index 151eb189c3..50d35bc64e 100644
--- a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
+++ b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
@@ -471,6 +471,32 @@ public class ByteBufferUtil
return bytes.getDouble(bytes.position());
}
+ public static ByteBuffer objectToBytes(Object obj)
+ {
+ if (obj instanceof Integer)
+ return ByteBufferUtil.bytes((int) obj);
+ else if (obj instanceof Byte)
+ return ByteBufferUtil.bytes((byte) obj);
+ else if (obj instanceof Short)
+ return ByteBufferUtil.bytes((short) obj);
+ else if (obj instanceof Long)
+ return ByteBufferUtil.bytes((long) obj);
+ else if (obj instanceof Float)
+ return ByteBufferUtil.bytes((float) obj);
+ else if (obj instanceof Double)
+ return ByteBufferUtil.bytes((double) obj);
+ else if (obj instanceof UUID)
+ return ByteBufferUtil.bytes((UUID) obj);
+ else if (obj instanceof InetAddress)
+ return ByteBufferUtil.bytes((InetAddress) obj);
+ else if (obj instanceof String)
+ return ByteBufferUtil.bytes((String) obj);
+ else
+ throw new IllegalArgumentException(String.format("Cannot convert value %s of type %s",
+ obj,
+ obj.getClass()));
+ }
+
public static ByteBuffer bytes(byte b)
{
return ByteBuffer.allocate(1).put(0, b);
diff --git a/src/java/org/apache/cassandra/utils/MBeanWrapper.java b/src/java/org/apache/cassandra/utils/MBeanWrapper.java
new file mode 100644
index 0000000000..edee6af652
--- /dev/null
+++ b/src/java/org/apache/cassandra/utils/MBeanWrapper.java
@@ -0,0 +1,179 @@
+/*
+ * 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.cassandra.utils;
+
+import java.lang.management.ManagementFactory;
+import java.util.function.Consumer;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper class to avoid catching and rethrowing checked exceptions on MBean and
+ * allow turning of MBean registration for test purposes.
+ */
+public interface MBeanWrapper
+{
+ static final Logger logger = LoggerFactory.getLogger(MBeanWrapper.class);
+
+ static final MBeanWrapper instance = Boolean.getBoolean("org.apache.cassandra.disable_mbean_registration") ?
+ new NoOpMBeanWrapper() :
+ new PlatformMBeanWrapper();
+
+ // Passing true for graceful will log exceptions instead of rethrowing them
+ public void registerMBean(Object obj, ObjectName mbeanName, OnException onException);
+ default void registerMBean(Object obj, ObjectName mbeanName)
+ {
+ registerMBean(obj, mbeanName, OnException.THROW);
+ }
+
+ public void registerMBean(Object obj, String mbeanName, OnException onException);
+ default void registerMBean(Object obj, String mbeanName)
+ {
+ registerMBean(obj, mbeanName, OnException.THROW);
+ }
+
+ public boolean isRegistered(ObjectName mbeanName, OnException onException);
+ default boolean isRegistered(ObjectName mbeanName)
+ {
+ return isRegistered(mbeanName, OnException.THROW);
+ }
+
+ public boolean isRegistered(String mbeanName, OnException onException);
+ default boolean isRegistered(String mbeanName)
+ {
+ return isRegistered(mbeanName, OnException.THROW);
+ }
+
+ public void unregisterMBean(ObjectName mbeanName, OnException onException);
+ default void unregisterMBean(ObjectName mbeanName)
+ {
+ unregisterMBean(mbeanName, OnException.THROW);
+ }
+
+ public void unregisterMBean(String mbeanName, OnException onException);
+ default void unregisterMBean(String mbeanName)
+ {
+ unregisterMBean(mbeanName, OnException.THROW);
+ }
+
+ static class NoOpMBeanWrapper implements MBeanWrapper
+ {
+ public void registerMBean(Object obj, ObjectName mbeanName, OnException onException) {}
+ public void registerMBean(Object obj, String mbeanName, OnException onException) {}
+ public boolean isRegistered(ObjectName mbeanName, OnException onException) { return false; }
+ public boolean isRegistered(String mbeanName, OnException onException) { return false; }
+ public void unregisterMBean(ObjectName mbeanName, OnException onException) {}
+ public void unregisterMBean(String mbeanName, OnException onException) {}
+ }
+
+ static class PlatformMBeanWrapper implements MBeanWrapper
+ {
+ private final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ public void registerMBean(Object obj, ObjectName mbeanName, OnException onException)
+ {
+ try
+ {
+ mbs.registerMBean(obj, mbeanName);
+ }
+ catch (Exception e)
+ {
+ onException.handler.accept(e);
+ }
+ }
+
+ public void registerMBean(Object obj, String mbeanName, OnException onException)
+ {
+ try
+ {
+ mbs.registerMBean(obj, new ObjectName(mbeanName));
+ }
+ catch (Exception e)
+ {
+ onException.handler.accept(e);
+ }
+ }
+
+ public boolean isRegistered(ObjectName mbeanName, OnException onException)
+ {
+ try
+ {
+ return mbs.isRegistered(mbeanName);
+ }
+ catch (Exception e)
+ {
+ onException.handler.accept(e);
+ }
+ return false;
+ }
+
+ public boolean isRegistered(String mbeanName, OnException onException)
+ {
+ try
+ {
+ return mbs.isRegistered(new ObjectName(mbeanName));
+ }
+ catch (Exception e)
+ {
+ onException.handler.accept(e);
+ }
+ return false;
+ }
+
+ public void unregisterMBean(ObjectName mbeanName, OnException onException)
+ {
+ try
+ {
+ mbs.unregisterMBean(mbeanName);
+ }
+ catch (Exception e)
+ {
+ onException.handler.accept(e);
+ }
+ }
+
+ public void unregisterMBean(String mbeanName, OnException onException)
+ {
+ try
+ {
+ mbs.unregisterMBean(new ObjectName(mbeanName));
+ }
+ catch (Exception e)
+ {
+ onException.handler.accept(e);
+ }
+ }
+ }
+
+ public enum OnException
+ {
+ THROW(e -> { throw new RuntimeException(e); }),
+ LOG(e -> { logger.error("Error in MBean wrapper: ", e); }),
+ IGNORE(e -> {});
+
+ private Consumer handler;
+ OnException(Consumer handler)
+ {
+ this.handler = handler;
+ }
+ }
+}
diff --git a/src/java/org/apache/cassandra/utils/Mx4jTool.java b/src/java/org/apache/cassandra/utils/Mx4jTool.java
index 5baaea2549..eda63543d4 100644
--- a/src/java/org/apache/cassandra/utils/Mx4jTool.java
+++ b/src/java/org/apache/cassandra/utils/Mx4jTool.java
@@ -17,8 +17,6 @@
*/
package org.apache.cassandra.utils;
-import java.lang.management.ManagementFactory;
-import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.apache.commons.lang3.StringUtils;
@@ -44,7 +42,7 @@ public class Mx4jTool
try
{
logger.trace("Will try to load mx4j now, if it's in the classpath");
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ MBeanWrapper mbs = MBeanWrapper.instance;
ObjectName processorName = new ObjectName("Server:name=XSLTProcessor");
Class> httpAdaptorClass = Class.forName("mx4j.tools.adaptor.http.HttpAdaptor");
diff --git a/src/java/org/apache/cassandra/utils/concurrent/Ref.java b/src/java/org/apache/cassandra/utils/concurrent/Ref.java
index b69e6bf911..1a17a1f4b8 100644
--- a/src/java/org/apache/cassandra/utils/concurrent/Ref.java
+++ b/src/java/org/apache/cassandra/utils/concurrent/Ref.java
@@ -31,6 +31,7 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import org.apache.cassandra.concurrent.InfiniteLoopExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -354,11 +355,10 @@ public final class Ref implements RefCounted
static final Set> concurrentIterables = Collections.newSetFromMap(new IdentityHashMap<>());
private static final Set globallyExtant = Collections.newSetFromMap(new ConcurrentHashMap<>());
static final ReferenceQueue