16
16
import com .google .common .base .Function ;
17
17
import com .google .common .base .Optional ;
18
18
import com .google .common .collect .Lists ;
19
+
19
20
import com .spotify .reaper .ReaperException ;
20
21
import com .spotify .reaper .core .Cluster ;
21
22
import com .spotify .reaper .service .RingRange ;
@@ -73,12 +74,14 @@ public class JmxProxy implements NotificationListener, AutoCloseable {
73
74
private final StorageServiceMBean ssProxy ;
74
75
private final Optional <RepairStatusHandler > repairStatusHandler ;
75
76
private final String host ;
77
+ private final JMXServiceURL jmxUrl ;
76
78
private final String clusterName ;
77
79
78
- private JmxProxy (Optional <RepairStatusHandler > handler , String host , JMXConnector jmxConnector ,
79
- StorageServiceMBean ssProxy , ObjectName ssMbeanName ,
80
- MBeanServerConnection mbeanServer , CompactionManagerMBean cmProxy ) {
80
+ private JmxProxy (Optional <RepairStatusHandler > handler , String host , JMXServiceURL jmxUrl ,
81
+ JMXConnector jmxConnector , StorageServiceMBean ssProxy , ObjectName ssMbeanName ,
82
+ MBeanServerConnection mbeanServer , CompactionManagerMBean cmProxy ) {
81
83
this .host = host ;
84
+ this .jmxUrl = jmxUrl ;
82
85
this .jmxConnector = jmxConnector ;
83
86
this .ssMbeanName = ssMbeanName ;
84
87
this .mbeanServer = mbeanServer ;
@@ -88,11 +91,12 @@ private JmxProxy(Optional<RepairStatusHandler> handler, String host, JMXConnecto
88
91
this .clusterName = Cluster .toSymbolicName (ssProxy .getClusterName ());
89
92
}
90
93
91
-
94
+
92
95
/**
93
96
* @see JmxProxy#connect(Optional, String, int, String, String)
94
97
*/
95
- static JmxProxy connect (Optional <RepairStatusHandler > handler , String host , String username , String password )
98
+ static JmxProxy connect (Optional <RepairStatusHandler > handler , String host , String username ,
99
+ String password )
96
100
throws ReaperException {
97
101
assert null != host : "null host given to JmxProxy.connect()" ;
98
102
String [] parts = host .split (":" );
@@ -103,22 +107,24 @@ static JmxProxy connect(Optional<RepairStatusHandler> handler, String host, Stri
103
107
}
104
108
}
105
109
106
-
110
+
107
111
/**
108
112
* Connect to JMX interface on the given host and port.
109
113
*
110
- * @param handler Implementation of {@link RepairStatusHandler} to process incoming notifications
111
- * of repair events.
112
- * @param host hostname or ip address of Cassandra node
113
- * @param port port number to use for JMX connection
114
+ * @param handler Implementation of {@link RepairStatusHandler} to process incoming
115
+ * notifications
116
+ * of repair events.
117
+ * @param host hostname or ip address of Cassandra node
118
+ * @param port port number to use for JMX connection
114
119
* @param username username to use for JMX authentication
115
120
* @param password password to use for JMX authentication
116
121
*/
117
- static JmxProxy connect (Optional <RepairStatusHandler > handler , String host , int port , String username , String password )
122
+ static JmxProxy connect (Optional <RepairStatusHandler > handler , String host , int port ,
123
+ String username , String password )
118
124
throws ReaperException {
119
- JMXServiceURL jmxUrl ;
120
125
ObjectName ssMbeanName ;
121
126
ObjectName cmMbeanName ;
127
+ JMXServiceURL jmxUrl ;
122
128
try {
123
129
jmxUrl = new JMXServiceURL (String .format (JMX_URL , host , port ));
124
130
ssMbeanName = new ObjectName (SS_OBJECT_NAME );
@@ -129,7 +135,7 @@ static JmxProxy connect(Optional<RepairStatusHandler> handler, String host, int
129
135
}
130
136
try {
131
137
Map <String , Object > env = new HashMap <String , Object >();
132
- if (username != null && password != null ) {
138
+ if (username != null && password != null ) {
133
139
String [] creds = {username , password };
134
140
env .put (JMXConnector .CREDENTIALS , creds );
135
141
}
@@ -139,12 +145,13 @@ static JmxProxy connect(Optional<RepairStatusHandler> handler, String host, int
139
145
JMX .newMBeanProxy (mbeanServerConn , ssMbeanName , StorageServiceMBean .class );
140
146
CompactionManagerMBean cmProxy =
141
147
JMX .newMBeanProxy (mbeanServerConn , cmMbeanName , CompactionManagerMBean .class );
142
- JmxProxy proxy =
143
- new JmxProxy ( handler , host , jmxConn , ssProxy , ssMbeanName , mbeanServerConn , cmProxy );
148
+ JmxProxy proxy = new JmxProxy ( handler , host , jmxUrl , jmxConn , ssProxy , ssMbeanName ,
149
+ mbeanServerConn , cmProxy );
144
150
// registering a listener throws bunch of exceptions, so we do it here rather than in the
145
151
// constructor
146
152
mbeanServerConn .addNotificationListener (ssMbeanName , proxy , null , null );
147
- LOG .debug (String .format ("JMX connection to %s properly connected." , host ));
153
+ LOG .debug (String .format ("JMX connection to %s properly connected: %s" ,
154
+ host , jmxUrl .toString ()));
148
155
return proxy ;
149
156
} catch (IOException | InstanceNotFoundException e ) {
150
157
LOG .error (String .format ("Failed to establish JMX connection to %s:%s" , host , port ));
@@ -293,13 +300,12 @@ public void cancelAllRepairs() {
293
300
294
301
/**
295
302
* Checks if table exists in the cluster by instantiating a MBean for that table.
296
- *
297
303
*/
298
304
public boolean tableExists (String ks , String cf ) {
299
305
try {
300
306
String type = cf .contains ("." ) ? "IndexColumnFamilies" : "ColumnFamilies" ;
301
307
String nameStr = String .format ("org.apache.cassandra.db:type=*%s,keyspace=%s,columnfamily=%s" ,
302
- type , ks , cf );
308
+ type , ks , cf );
303
309
Set <ObjectName > beans = mbeanServer .queryNames (new ObjectName (nameStr ), null );
304
310
if (beans .isEmpty () || beans .size () != 1 ) {
305
311
return false ;
@@ -308,7 +314,7 @@ public boolean tableExists(String ks, String cf) {
308
314
JMX .newMBeanProxy (mbeanServer , bean , ColumnFamilyStoreMBean .class );
309
315
} catch (MalformedObjectNameException | IOException e ) {
310
316
String errMsg = String .format ("ColumnFamilyStore for %s/%s not found: %s" , ks , cf ,
311
- e .getMessage ());
317
+ e .getMessage ());
312
318
LOG .warn (errMsg );
313
319
return false ;
314
320
}
@@ -323,7 +329,7 @@ public boolean tableExists(String ks, String cf) {
323
329
* @return Repair command number, or 0 if nothing to repair
324
330
*/
325
331
public int triggerRepair (BigInteger beginToken , BigInteger endToken , String keyspace ,
326
- RepairParallelism repairParallelism , Collection <String > columnFamilies ) {
332
+ RepairParallelism repairParallelism , Collection <String > columnFamilies ) {
327
333
checkNotNull (ssProxy , "Looks like the proxy is not connected" );
328
334
String cassandraVersion = ssProxy .getReleaseVersion ();
329
335
boolean canUseDatacenterAware = false ;
@@ -336,27 +342,27 @@ public int triggerRepair(BigInteger beginToken, BigInteger endToken, String keys
336
342
+ "host %s, with repair parallelism %s, in cluster with Cassandra "
337
343
+ "version '%s' (can use DATACENTER_AWARE '%s'), "
338
344
+ "for column families: %s" ,
339
- beginToken .toString (), endToken .toString (), keyspace , this .host ,
340
- repairParallelism , cassandraVersion , canUseDatacenterAware ,
341
- columnFamilies );
345
+ beginToken .toString (), endToken .toString (), keyspace , this .host ,
346
+ repairParallelism , cassandraVersion , canUseDatacenterAware ,
347
+ columnFamilies );
342
348
LOG .info (msg );
343
349
if (repairParallelism .equals (RepairParallelism .DATACENTER_AWARE )) {
344
350
if (canUseDatacenterAware ) {
345
351
return ssProxy .forceRepairRangeAsync (beginToken .toString (), endToken .toString (), keyspace ,
346
- repairParallelism .ordinal (), null , null ,
347
- columnFamilies
348
- .toArray (new String [columnFamilies .size ()]));
352
+ repairParallelism .ordinal (), null , null ,
353
+ columnFamilies
354
+ .toArray (new String [columnFamilies .size ()]));
349
355
} else {
350
356
LOG .info ("Cannot use DATACENTER_AWARE repair policy for Cassandra cluster with version {},"
351
357
+ " falling back to SEQUENTIAL repair." ,
352
- cassandraVersion );
358
+ cassandraVersion );
353
359
repairParallelism = RepairParallelism .SEQUENTIAL ;
354
360
}
355
361
}
356
362
boolean snapshotRepair = repairParallelism .equals (RepairParallelism .SEQUENTIAL );
357
363
return ssProxy .forceRepairRangeAsync (beginToken .toString (), endToken .toString (), keyspace ,
358
- snapshotRepair , false ,
359
- columnFamilies .toArray (new String [columnFamilies .size ()]));
364
+ snapshotRepair , false ,
365
+ columnFamilies .toArray (new String [columnFamilies .size ()]));
360
366
}
361
367
362
368
/**
@@ -404,11 +410,18 @@ public boolean isConnectionAlive() {
404
410
*/
405
411
@ Override
406
412
public void close () throws ReaperException {
413
+ LOG .debug (String .format ("close JMX connection to '%s': %s" , host , jmxUrl ));
407
414
try {
408
415
mbeanServer .removeNotificationListener (ssMbeanName , this );
416
+ } catch (InstanceNotFoundException | ListenerNotFoundException | IOException e ) {
417
+ LOG .warn ("failed on removing notification listener" );
418
+ e .printStackTrace ();
419
+ }
420
+ try {
409
421
jmxConnector .close ();
410
- } catch (IOException | InstanceNotFoundException | ListenerNotFoundException e ) {
411
- throw new ReaperException (e );
422
+ } catch (IOException e ) {
423
+ LOG .warn ("failed closing a JMX connection" );
424
+ e .printStackTrace ();
412
425
}
413
426
}
414
427
0 commit comments