Skip to content

Commit 3037281

Browse files
committed
[bugfix] Fix issues that stop the JMX Client from running correctly
Closes eXist-db/exist#5706
1 parent 806a8b8 commit 3037281

File tree

6 files changed

+230
-57
lines changed

6 files changed

+230
-57
lines changed

exist-core/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,11 @@
855855
<include>src/main/java/org/exist/launcher/SplashScreen.java</include>
856856
<include>src/main/java/org/exist/launcher/WindowsServiceManager.java</include>
857857
<include>src/main/java/org/exist/management/client/JMXClient.java</include>
858+
<include>src/main/java/org/exist/management/impl/Database.java</include>
859+
<include>src/main/java/org/exist/management/impl/DatabaseMXBean.java</include>
858860
<include>src/main/java/org/exist/management/impl/ExistMBean.java</include>
861+
<include>src/main/java/org/exist/management/impl/CollectionCache.java</include>
862+
<include>src/main/java/org/exist/management/impl/CollectionCacheMXBean.java</include>
859863
<include>src/main/java/org/exist/protocolhandler/xmldb/XmldbURL.java</include>
860864
<include>src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java</include>
861865
<include>src/main/java/org/exist/repo/ClasspathHelper.java</include>
@@ -1066,7 +1070,11 @@
10661070
<exclude>src/main/java/org/exist/launcher/SplashScreen.java</exclude>
10671071
<exclude>src/main/java/org/exist/launcher/WindowsServiceManager.java</exclude>
10681072
<exclude>src/main/java/org/exist/management/client/JMXClient.java</exclude>
1073+
<exclude>src/main/java/org/exist/management/impl/Database.java</exclude>
1074+
<exclude>src/main/java/org/exist/management/impl/DatabaseMXBean.java</exclude>
10691075
<exclude>src/main/java/org/exist/management/impl/ExistMBean.java</exclude>
1076+
<exclude>src/main/java/org/exist/management/impl/CollectionCache.java</exclude>
1077+
<exclude>src/main/java/org/exist/management/impl/CollectionCacheMXBean.java</exclude>
10701078
<exclude>src/main/java/org/exist/protocolhandler/xmldb/XmldbURL.java</exclude>
10711079
<exclude>src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java</exclude>
10721080
<exclude>src/main/java/org/exist/repo/ClasspathHelper.java</exclude>

exist-core/src/main/java/org/exist/management/client/JMXClient.java

Lines changed: 106 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@
4747

4848
import org.exist.start.CompatibleJavaVersionCheck;
4949
import org.exist.start.StartException;
50+
import org.exist.util.FileUtils;
5051
import org.exist.util.OSUtil;
5152
import org.exist.util.SystemExitCodes;
5253
import se.softhouse.jargo.Argument;
5354
import se.softhouse.jargo.ArgumentException;
5455
import se.softhouse.jargo.CommandLineParser;
5556
import se.softhouse.jargo.ParsedArguments;
5657

58+
import javax.annotation.Nullable;
5759
import javax.management.Attribute;
5860
import javax.management.AttributeList;
5961
import javax.management.AttributeNotFoundException;
@@ -64,6 +66,7 @@
6466
import javax.management.ObjectName;
6567
import javax.management.ReflectionException;
6668
import javax.management.openmbean.CompositeData;
69+
import javax.management.openmbean.CompositeDataSupport;
6770
import javax.management.openmbean.TabularData;
6871
import javax.management.remote.JMXConnector;
6972
import javax.management.remote.JMXConnectorFactory;
@@ -103,9 +106,9 @@ public void memoryStats() {
103106
final CompositeData composite = (CompositeData) connection.getAttribute(name, "HeapMemoryUsage");
104107
if (composite != null) {
105108
echo("\nMEMORY:");
106-
echo(String.format("Current heap: %,12d k Committed memory: %,12d k",
107-
((Long)composite.get("used")) / 1024, ((Long)composite.get("committed")) / 1024));
108-
echo(String.format("Max memory: %,12d k", ((Long)composite.get("max")) / 1024));
109+
echo(String.format("Current heap: %12s Committed memory: %12s",
110+
FileUtils.humanSize((Long)composite.get("used")), FileUtils.humanSize((Long)composite.get("committed"))));
111+
echo(String.format("Max memory: %12s", FileUtils.humanSize((Long)composite.get("max"))));
109112
}
110113
} catch (final Exception e) {
111114
error(e);
@@ -116,23 +119,24 @@ public void instanceStats() {
116119
try {
117120
echo("\nINSTANCE:");
118121
final ObjectName name = new ObjectName("org.exist.management." + instance + ":type=Database");
122+
echo(String.format("%25s: %10s", "Name", instance));
119123
final Long memReserved = (Long) connection.getAttribute(name, "ReservedMem");
120-
echo(String.format("%25s: %10d k", "Reserved memory", memReserved / 1024));
124+
echo(String.format("%25s: %10s", "Reserved memory", FileUtils.humanSize(memReserved)));
121125
final Long memCache = (Long) connection.getAttribute(name, "CacheMem");
122-
echo(String.format("%25s: %10d k", "Cache memory", memCache / 1024));
126+
echo(String.format("%25s: %10s", "Cache memory", FileUtils.humanSize(memCache)));
123127
final Long memCollCache = (Long) connection.getAttribute(name, "CollectionCacheMem");
124-
echo(String.format("%25s: %10d k", "Collection cache memory", memCollCache / 1024));
128+
echo(String.format("%25s: %10s", "Collection cache memory", FileUtils.humanSize(memCollCache)));
125129

126-
final String cols[] = { "MaxBrokers", "AvailableBrokers", "ActiveBrokers" };
130+
final String[] cols = { "MaxBrokers", "AvailableBrokers", "ActiveBrokers" };
127131
echo(String.format("\n%17s %17s %17s", cols[0], cols[1], cols[2]));
128132
final AttributeList attrs = connection.getAttributes(name, cols);
129-
final Object values[] = getValues(attrs);
130-
echo(String.format("%17d %17d %17d", values[0], values[1], values[2]));
133+
final Object[] values = getValues(attrs);
134+
echo(String.format("%17d %17d %17d", (Integer)values[0], (Integer)values[1], (Integer)values[2]));
131135

132136
final TabularData table = (TabularData) connection.getAttribute(name, "ActiveBrokersMap");
133-
if (table.size() > 0) {
137+
// if (table.size() > 0) {
134138
echo("\nCurrently active threads:");
135-
}
139+
// }
136140

137141
for (Object o : table.values()) {
138142
final CompositeData data = (CompositeData) o;
@@ -146,59 +150,100 @@ public void instanceStats() {
146150
public void cacheStats() {
147151
try {
148152
ObjectName name = new ObjectName("org.exist.management." + instance + ":type=CacheManager");
149-
String cols[] = { "MaxTotal", "CurrentSize" };
153+
String[] cols = { "MaxTotal", "CurrentSize" };
150154
AttributeList attrs = connection.getAttributes(name, cols);
151-
Object values[] = getValues(attrs);
155+
Object[] values = getValues(attrs);
152156
echo(String.format("\nCACHE [%8d pages max. / %8d pages allocated]", values[0], values[1]));
153157

154158
final Set<ObjectName> beans = connection.queryNames(new ObjectName("org.exist.management." + instance + ":type=CacheManager.Cache,*"), null);
155-
cols = new String[] {"Type", "FileName", "Size", "Used", "Hits", "Fails"};
159+
cols = new String[] {"Type", "CacheName", "Size", "Used", "Hits", "Fails"};
156160
echo(String.format("%10s %20s %10s %10s %10s %10s", cols[0], cols[1], cols[2], cols[3], cols[4], cols[5]));
157-
for (ObjectName bean : beans) {
161+
for (final ObjectName bean : beans) {
158162
name = bean;
159163
attrs = connection.getAttributes(name, cols);
160164
values = getValues(attrs);
161165
echo(String.format("%10s %20s %,10d %,10d %,10d %,10d", values[0], values[1], values[2], values[3], values[4], values[5]));
162166
}
163-
167+
164168
echo("");
165-
name = new ObjectName("org.exist.management." + instance + ":type=CollectionCacheManager");
166-
cols = new String[] { "MaxTotal", "CurrentSize" };
169+
name = new ObjectName("org.exist.management." + instance + ":type=CollectionCache");
170+
cols = new String[] { "MaxCacheSize", "Statistics" };
167171
attrs = connection.getAttributes(name, cols);
168172
values = getValues(attrs);
169-
echo(String.format("Collection Cache: %10d k max / %10d k allocated",
170-
((Long)values[0] / 1024), ((Long)values[1] / 1024)));
173+
174+
175+
echo(String.format("COLLECTION CACHE: [%10s max]", FileUtils.humanSize((Integer)values[0])));
176+
177+
cols = new String[] {"Hit Count", "Miss Count", "Load Success Count", "Load Failure Count", "Total Load Time", "Eviction Count", "Eviction Weight"};
178+
echo(String.format("%10s %20s %20s %20s %20s %20s %20s", cols[0], cols[1], cols[2], cols[3], cols[4], cols[5], cols[6]));
179+
final CompositeDataSupport statistics = (CompositeDataSupport) values[1];
180+
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")));
181+
171182
} catch (final Exception e) {
172183
error(e);
173184
}
174185
}
175186

176187
public void lockTable() {
177-
echo("\nList of threads currently waiting for a lock:");
188+
echo("\nList of threads attempting to acquire a lock:");
178189
echo("-----------------------------------------------");
179190
try {
180-
final TabularData table = (TabularData) connection.getAttribute(new ObjectName("org.exist.management:type=LockManager"), "WaitingThreads");
181-
for (Object o : table.values()) {
182-
final CompositeData data = (CompositeData) o;
183-
echo("Thread " + data.get("waitingThread"));
184-
echo(String.format("%20s: %s", "Lock type", data.get("lockType")));
185-
echo(String.format("%20s: %s", "Lock mode", data.get("lockMode")));
186-
echo(String.format("%20s: %s", "Lock id", data.get("id")));
187-
echo(String.format("%20s: %s", "Held by", Arrays.toString((String[]) data.get("owner"))));
188-
final String[] readers = (String[]) data.get("waitingForRead");
189-
if (readers.length > 0) {
190-
echo(String.format("%20s: %s", "Wait for read", Arrays.toString(readers)));
191-
}
192-
final String[] writers = (String[]) data.get("waitingForWrite");
193-
if (writers.length > 0) {
194-
echo(String.format("%20s: %s", "Wait for write", Arrays.toString(writers)));
195-
}
196-
}
191+
final TabularData table = (TabularData) connection.getAttribute(new ObjectName("org.exist.management." + instance + ":type=LockTable"), "Attempting");
192+
printLockTable(table);
193+
} catch (final MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | IOException | MalformedObjectNameException e) {
194+
error(e);
195+
}
196+
197+
echo("");
198+
199+
echo("\nList of threads holding a lock:");
200+
echo("-----------------------------------------------");
201+
try {
202+
final TabularData table = (TabularData) connection.getAttribute(new ObjectName("org.exist.management." + instance + ":type=LockTable"), "Acquired");
203+
printLockTable(table);
197204
} catch (final MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | IOException | MalformedObjectNameException e) {
198205
error(e);
199206
}
200207
}
201208

209+
private void printLockTable(final TabularData table) {
210+
for (final Object tv : table.values()) {
211+
final CompositeData data = (CompositeData) tv;
212+
213+
final String resourceUri = (String) data.get("key");
214+
echo("URI: " + resourceUri);
215+
216+
final TabularData valueData = (TabularData) data.get("value");
217+
for (final Object vdv : valueData.values()) {
218+
final CompositeData cvdv = (CompositeData) vdv;
219+
final String resourceType = (String) cvdv.get("key");
220+
echo(String.format("%20s: %s", "Lock type", resourceType));
221+
222+
final TabularData resourceData = (TabularData) cvdv.get("value");
223+
224+
for (final Object rvdv : resourceData.values()) {
225+
final CompositeData crvdv = (CompositeData) rvdv;
226+
final String lockMode = (String) crvdv.get("key");
227+
echo(String.format("%20s: %s", "Lock type", lockMode));
228+
229+
final TabularData lockData = (TabularData) crvdv.get("value");
230+
231+
for (final Object lrvdv : lockData.values()) {
232+
final CompositeData clrvdv = (CompositeData) lrvdv;
233+
final String owner = (String) clrvdv.get("key");
234+
echo(String.format("%20s: %s", "Held by", owner));
235+
236+
final CompositeData ownerData = (CompositeData) clrvdv.get("value");
237+
238+
final Integer holdCount = (Integer) ownerData.get("count");
239+
echo(String.format("%20s: %d", "Hold count", holdCount));
240+
}
241+
}
242+
243+
}
244+
}
245+
}
246+
202247
public void sanityReport() {
203248
echo("\nSanity report");
204249
echo("-----------------------------------------------");
@@ -213,12 +258,27 @@ public void sanityReport() {
213258
if (lastCheckStart != null && lastCheckEnd != null)
214259
{echo(String.format("%22s: %dms", "Check took", (lastCheckEnd.getTime() - lastCheckStart.getTime())));}
215260

216-
final TabularData table = (TabularData)
217-
connection.getAttribute(name, "Errors");
218-
for (Object o : table.values()) {
219-
final CompositeData data = (CompositeData) o;
220-
echo(String.format("%22s: %s", "Error code", data.get("errcode")));
221-
echo(String.format("%22s: %s", "Description", data.get("description")));
261+
@Nullable final Object result = connection.getAttribute(name, "Errors");
262+
if (result != null) {
263+
@Nullable final CompositeData table;
264+
if (result.getClass().isArray()) {
265+
final CompositeData[] tables = ((CompositeData[]) result);
266+
if (tables.length > 0) {
267+
table = tables[0];
268+
} else {
269+
table = null;
270+
}
271+
} else {
272+
table = (CompositeData) result;
273+
}
274+
275+
if (table != null) {
276+
for (final Object o : table.values()) {
277+
final CompositeData data = (CompositeData) o;
278+
echo(String.format("%22s: %s", "Error code", data.get("errcode")));
279+
echo(String.format("%22s: %s", "Description", data.get("description")));
280+
}
281+
}
222282
}
223283
} catch (final MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | IOException | MalformedObjectNameException e) {
224284
error(e);
@@ -255,10 +315,10 @@ public void jobReport() {
255315
}
256316
}
257317

258-
private Object[] getValues(AttributeList attribs) {
318+
private Object[] getValues(final AttributeList attribs) {
259319
final Object[] v = new Object[attribs.size()];
260320
for (int i = 0; i < attribs.size(); i++) {
261-
v[i] = ((Attribute)attribs.get(i)).getValue();
321+
v[i] = ((Attribute) attribs.get(i)).getValue();
262322
}
263323
return v;
264324
}

exist-core/src/main/java/org/exist/management/impl/CollectionCache.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
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+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -19,7 +43,6 @@
1943
* License along with this library; if not, write to the Free Software
2044
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2145
*/
22-
2346
package org.exist.management.impl;
2447

2548
import org.exist.storage.BrokerPool;
@@ -58,6 +81,11 @@ public String getInstanceId() {
5881
return instance.getId();
5982
}
6083

84+
@Override
85+
public int getMaxCacheSize() {
86+
return instance.getCollectionsCache().getMaxCacheSize();
87+
}
88+
6189
@Override
6290
public org.exist.collections.CollectionCache.Statistics getStatistics() {
6391
return instance.getCollectionsCache().getStatistics();

exist-core/src/main/java/org/exist/management/impl/CollectionCacheMXBean.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
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+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -19,7 +43,6 @@
1943
* License along with this library; if not, write to the Free Software
2044
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2145
*/
22-
2346
package org.exist.management.impl;
2447

2548
import org.exist.collections.CollectionCache;
@@ -31,6 +54,13 @@
3154
*/
3255
public interface CollectionCacheMXBean extends PerInstanceMBean {
3356

57+
/**
58+
* Returns the maximum size of the cache in bytes
59+
*
60+
* @return maximum size of the cache in bytes
61+
*/
62+
int getMaxCacheSize();
63+
3464
/**
3565
* Get a statistics snapshot of the Collection Cache
3666
*

0 commit comments

Comments
 (0)