1
1
/*
2
+ * Elemental
3
+ * Copyright (C) 2024, Evolved Binary Ltd
4
+ *
5
+
6
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
7
+ *
8
+ * This library is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; version 2.1.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ *
21
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22
+ * The original license header is included below.
23
+ *
24
+ * =====================================================================
25
+ *
2
26
* eXist-db Open Source Native XML Database
3
27
* Copyright (C) 2001 The eXist-db Authors
4
28
*
23
47
24
48
import org .exist .start .CompatibleJavaVersionCheck ;
25
49
import org .exist .start .StartException ;
50
+ import org .exist .util .FileUtils ;
26
51
import org .exist .util .SystemExitCodes ;
27
52
import se .softhouse .jargo .Argument ;
28
53
import se .softhouse .jargo .ArgumentException ;
29
54
import se .softhouse .jargo .CommandLineParser ;
30
55
import se .softhouse .jargo .ParsedArguments ;
31
56
57
+ import javax .annotation .Nullable ;
32
58
import javax .management .Attribute ;
33
59
import javax .management .AttributeList ;
34
60
import javax .management .AttributeNotFoundException ;
39
65
import javax .management .ObjectName ;
40
66
import javax .management .ReflectionException ;
41
67
import javax .management .openmbean .CompositeData ;
68
+ import javax .management .openmbean .CompositeDataSupport ;
42
69
import javax .management .openmbean .TabularData ;
43
70
import javax .management .remote .JMXConnector ;
44
71
import javax .management .remote .JMXConnectorFactory ;
@@ -78,9 +105,9 @@ public void memoryStats() {
78
105
final CompositeData composite = (CompositeData ) connection .getAttribute (name , "HeapMemoryUsage" );
79
106
if (composite != null ) {
80
107
echo ("\n MEMORY:" );
81
- echo (String .format ("Current heap: %,12d k Committed memory: %,12d k " ,
82
- ((Long )composite .get ("used" )) / 1024 , ((Long )composite .get ("committed" )) / 1024 ));
83
- echo (String .format ("Max memory: %,12d k " , ((Long )composite .get ("max" )) / 1024 ));
108
+ echo (String .format ("Current heap: %12s Committed memory: %12s " ,
109
+ FileUtils . humanSize ((Long )composite .get ("used" )), FileUtils . humanSize ((Long )composite .get ("committed" ))));
110
+ echo (String .format ("Max memory: %12s " , FileUtils . humanSize ((Long )composite .get ("max" ))));
84
111
}
85
112
} catch (final Exception e ) {
86
113
error (e );
@@ -91,23 +118,24 @@ public void instanceStats() {
91
118
try {
92
119
echo ("\n INSTANCE:" );
93
120
final ObjectName name = new ObjectName ("org.exist.management." + instance + ":type=Database" );
121
+ echo (String .format ("%25s: %10s" , "Name" , instance ));
94
122
final Long memReserved = (Long ) connection .getAttribute (name , "ReservedMem" );
95
- echo (String .format ("%25s: %10d k " , "Reserved memory" , memReserved / 1024 ));
123
+ echo (String .format ("%25s: %10s " , "Reserved memory" , FileUtils . humanSize ( memReserved ) ));
96
124
final Long memCache = (Long ) connection .getAttribute (name , "CacheMem" );
97
- echo (String .format ("%25s: %10d k " , "Cache memory" , memCache / 1024 ));
125
+ echo (String .format ("%25s: %10s " , "Cache memory" , FileUtils . humanSize ( memCache ) ));
98
126
final Long memCollCache = (Long ) connection .getAttribute (name , "CollectionCacheMem" );
99
- echo (String .format ("%25s: %10d k " , "Collection cache memory" , memCollCache / 1024 ));
127
+ echo (String .format ("%25s: %10s " , "Collection cache memory" , FileUtils . humanSize ( memCollCache ) ));
100
128
101
- final String cols [] = { "MaxBrokers" , "AvailableBrokers" , "ActiveBrokers" };
129
+ final String [] cols = { "MaxBrokers" , "AvailableBrokers" , "ActiveBrokers" };
102
130
echo (String .format ("\n %17s %17s %17s" , cols [0 ], cols [1 ], cols [2 ]));
103
131
final AttributeList attrs = connection .getAttributes (name , cols );
104
- final Object values [] = getValues (attrs );
105
- echo (String .format ("%17d %17d %17d" , values [0 ], values [1 ], values [2 ]));
132
+ final Object [] values = getValues (attrs );
133
+ echo (String .format ("%17d %17d %17d" , ( Integer ) values [0 ], ( Integer ) values [1 ], ( Integer ) values [2 ]));
106
134
107
135
final TabularData table = (TabularData ) connection .getAttribute (name , "ActiveBrokersMap" );
108
- if (table .size () > 0 ) {
136
+ // if (table.size() > 0) {
109
137
echo ("\n Currently active threads:" );
110
- }
138
+ // }
111
139
112
140
for (Object o : table .values ()) {
113
141
final CompositeData data = (CompositeData ) o ;
@@ -121,59 +149,100 @@ public void instanceStats() {
121
149
public void cacheStats () {
122
150
try {
123
151
ObjectName name = new ObjectName ("org.exist.management." + instance + ":type=CacheManager" );
124
- String cols [] = { "MaxTotal" , "CurrentSize" };
152
+ String [] cols = { "MaxTotal" , "CurrentSize" };
125
153
AttributeList attrs = connection .getAttributes (name , cols );
126
- Object values [] = getValues (attrs );
154
+ Object [] values = getValues (attrs );
127
155
echo (String .format ("\n CACHE [%8d pages max. / %8d pages allocated]" , values [0 ], values [1 ]));
128
156
129
157
final Set <ObjectName > beans = connection .queryNames (new ObjectName ("org.exist.management." + instance + ":type=CacheManager.Cache,*" ), null );
130
- cols = new String [] {"Type" , "FileName " , "Size" , "Used" , "Hits" , "Fails" };
158
+ cols = new String [] {"Type" , "CacheName " , "Size" , "Used" , "Hits" , "Fails" };
131
159
echo (String .format ("%10s %20s %10s %10s %10s %10s" , cols [0 ], cols [1 ], cols [2 ], cols [3 ], cols [4 ], cols [5 ]));
132
- for (ObjectName bean : beans ) {
160
+ for (final ObjectName bean : beans ) {
133
161
name = bean ;
134
162
attrs = connection .getAttributes (name , cols );
135
163
values = getValues (attrs );
136
164
echo (String .format ("%10s %20s %,10d %,10d %,10d %,10d" , values [0 ], values [1 ], values [2 ], values [3 ], values [4 ], values [5 ]));
137
165
}
138
-
166
+
139
167
echo ("" );
140
- name = new ObjectName ("org.exist.management." + instance + ":type=CollectionCacheManager " );
141
- cols = new String [] { "MaxTotal " , "CurrentSize " };
168
+ name = new ObjectName ("org.exist.management." + instance + ":type=CollectionCache " );
169
+ cols = new String [] { "MaxCacheSize " , "Statistics " };
142
170
attrs = connection .getAttributes (name , cols );
143
171
values = getValues (attrs );
144
- echo (String .format ("Collection Cache: %10d k max / %10d k allocated" ,
145
- ((Long )values [0 ] / 1024 ), ((Long )values [1 ] / 1024 )));
172
+
173
+
174
+ echo (String .format ("COLLECTION CACHE: [%10s max]" , FileUtils .humanSize ((Integer )values [0 ])));
175
+
176
+ cols = new String [] {"Hit Count" , "Miss Count" , "Load Success Count" , "Load Failure Count" , "Total Load Time" , "Eviction Count" , "Eviction Weight" };
177
+ echo (String .format ("%10s %20s %20s %20s %20s %20s %20s" , cols [0 ], cols [1 ], cols [2 ], cols [3 ], cols [4 ], cols [5 ], cols [6 ]));
178
+ final CompositeDataSupport statistics = (CompositeDataSupport ) values [1 ];
179
+ echo (String .format ("%10d %20d %20d %20d %20d %20d %20d" , (Long )statistics .get ("hitCount" ), (Long )statistics .get ("missCount" ), (Long )statistics .get ("loadSuccessCount" ), (Long )statistics .get ("loadFailureCount" ), (Long )statistics .get ("totalLoadTime" ), (Long )statistics .get ("evictionCount" ), (Long )statistics .get ("evictionWeight" )));
180
+
146
181
} catch (final Exception e ) {
147
182
error (e );
148
183
}
149
184
}
150
185
151
186
public void lockTable () {
152
- echo ("\n List of threads currently waiting for a lock:" );
187
+ echo ("\n List of threads attempting to acquire a lock:" );
153
188
echo ("-----------------------------------------------" );
154
189
try {
155
- final TabularData table = (TabularData ) connection .getAttribute (new ObjectName ("org.exist.management:type=LockManager" ), "WaitingThreads" );
156
- for (Object o : table .values ()) {
157
- final CompositeData data = (CompositeData ) o ;
158
- echo ("Thread " + data .get ("waitingThread" ));
159
- echo (String .format ("%20s: %s" , "Lock type" , data .get ("lockType" )));
160
- echo (String .format ("%20s: %s" , "Lock mode" , data .get ("lockMode" )));
161
- echo (String .format ("%20s: %s" , "Lock id" , data .get ("id" )));
162
- echo (String .format ("%20s: %s" , "Held by" , Arrays .toString ((String []) data .get ("owner" ))));
163
- final String [] readers = (String []) data .get ("waitingForRead" );
164
- if (readers .length > 0 ) {
165
- echo (String .format ("%20s: %s" , "Wait for read" , Arrays .toString (readers )));
166
- }
167
- final String [] writers = (String []) data .get ("waitingForWrite" );
168
- if (writers .length > 0 ) {
169
- echo (String .format ("%20s: %s" , "Wait for write" , Arrays .toString (writers )));
170
- }
171
- }
190
+ final TabularData table = (TabularData ) connection .getAttribute (new ObjectName ("org.exist.management." + instance + ":type=LockTable" ), "Attempting" );
191
+ printLockTable (table );
192
+ } catch (final MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | IOException | MalformedObjectNameException e ) {
193
+ error (e );
194
+ }
195
+
196
+ echo ("" );
197
+
198
+ echo ("\n List of threads holding a lock:" );
199
+ echo ("-----------------------------------------------" );
200
+ try {
201
+ final TabularData table = (TabularData ) connection .getAttribute (new ObjectName ("org.exist.management." + instance + ":type=LockTable" ), "Acquired" );
202
+ printLockTable (table );
172
203
} catch (final MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | IOException | MalformedObjectNameException e ) {
173
204
error (e );
174
205
}
175
206
}
176
207
208
+ private void printLockTable (final TabularData table ) {
209
+ for (final Object tv : table .values ()) {
210
+ final CompositeData data = (CompositeData ) tv ;
211
+
212
+ final String resourceUri = (String ) data .get ("key" );
213
+ echo ("URI: " + resourceUri );
214
+
215
+ final TabularData valueData = (TabularData ) data .get ("value" );
216
+ for (final Object vdv : valueData .values ()) {
217
+ final CompositeData cvdv = (CompositeData ) vdv ;
218
+ final String resourceType = (String ) cvdv .get ("key" );
219
+ echo (String .format ("%20s: %s" , "Lock type" , resourceType ));
220
+
221
+ final TabularData resourceData = (TabularData ) cvdv .get ("value" );
222
+
223
+ for (final Object rvdv : resourceData .values ()) {
224
+ final CompositeData crvdv = (CompositeData ) rvdv ;
225
+ final String lockMode = (String ) crvdv .get ("key" );
226
+ echo (String .format ("%20s: %s" , "Lock type" , lockMode ));
227
+
228
+ final TabularData lockData = (TabularData ) crvdv .get ("value" );
229
+
230
+ for (final Object lrvdv : lockData .values ()) {
231
+ final CompositeData clrvdv = (CompositeData ) lrvdv ;
232
+ final String owner = (String ) clrvdv .get ("key" );
233
+ echo (String .format ("%20s: %s" , "Held by" , owner ));
234
+
235
+ final CompositeData ownerData = (CompositeData ) clrvdv .get ("value" );
236
+
237
+ final Integer holdCount = (Integer ) ownerData .get ("count" );
238
+ echo (String .format ("%20s: %d" , "Hold count" , holdCount ));
239
+ }
240
+ }
241
+
242
+ }
243
+ }
244
+ }
245
+
177
246
public void sanityReport () {
178
247
echo ("\n Sanity report" );
179
248
echo ("-----------------------------------------------" );
@@ -188,12 +257,27 @@ public void sanityReport() {
188
257
if (lastCheckStart != null && lastCheckEnd != null )
189
258
{echo (String .format ("%22s: %dms" , "Check took" , (lastCheckEnd .getTime () - lastCheckStart .getTime ())));}
190
259
191
- final TabularData table = (TabularData )
192
- connection .getAttribute (name , "Errors" );
193
- for (Object o : table .values ()) {
194
- final CompositeData data = (CompositeData ) o ;
195
- echo (String .format ("%22s: %s" , "Error code" , data .get ("errcode" )));
196
- echo (String .format ("%22s: %s" , "Description" , data .get ("description" )));
260
+ @ Nullable final Object result = connection .getAttribute (name , "Errors" );
261
+ if (result != null ) {
262
+ @ Nullable final CompositeData table ;
263
+ if (result .getClass ().isArray ()) {
264
+ final CompositeData [] tables = ((CompositeData []) result );
265
+ if (tables .length > 0 ) {
266
+ table = tables [0 ];
267
+ } else {
268
+ table = null ;
269
+ }
270
+ } else {
271
+ table = (CompositeData ) result ;
272
+ }
273
+
274
+ if (table != null ) {
275
+ for (final Object o : table .values ()) {
276
+ final CompositeData data = (CompositeData ) o ;
277
+ echo (String .format ("%22s: %s" , "Error code" , data .get ("errcode" )));
278
+ echo (String .format ("%22s: %s" , "Description" , data .get ("description" )));
279
+ }
280
+ }
197
281
}
198
282
} catch (final MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | IOException | MalformedObjectNameException e ) {
199
283
error (e );
@@ -230,10 +314,10 @@ public void jobReport() {
230
314
}
231
315
}
232
316
233
- private Object [] getValues (AttributeList attribs ) {
317
+ private Object [] getValues (final AttributeList attribs ) {
234
318
final Object [] v = new Object [attribs .size ()];
235
319
for (int i = 0 ; i < attribs .size (); i ++) {
236
- v [i ] = ((Attribute )attribs .get (i )).getValue ();
320
+ v [i ] = ((Attribute ) attribs .get (i )).getValue ();
237
321
}
238
322
return v ;
239
323
}
@@ -256,17 +340,14 @@ private void error(Exception e) {
256
340
/* connection arguments */
257
341
private static final Argument <String > addressArg = stringArgument ("-a" , "--address" )
258
342
.description ("RMI address of the server" )
259
- .required ()
260
343
.defaultValue ("localhost" )
261
344
.build ();
262
345
private static final Argument <Integer > portArg = integerArgument ("-p" , "--port" )
263
346
.description ("RMI port of the server" )
264
- .required ()
265
347
.defaultValue (DEFAULT_PORT )
266
348
.build ();
267
349
private static final Argument <String > instanceArg = stringArgument ("-i" , "--instance" )
268
350
.description ("The ID of the database instance to connect to" )
269
- .required ()
270
351
.defaultValue ("exist" )
271
352
.build ();
272
353
private static final Argument <Integer > waitArg = integerArgument ("-w" , "--wait" )
0 commit comments