1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.jmx; |
7 | |
8 | import java.lang.management.ManagementFactory; |
9 | |
10 | import java.sql.Timestamp; |
11 | import java.util.Hashtable; |
12 | import java.util.Map; |
13 | import java.util.TreeMap; |
14 | import javax.management.JMException; |
15 | import javax.management.MBeanServer; |
16 | import javax.management.ObjectName; |
17 | import org.h2.command.Command; |
18 | import org.h2.engine.ConnectionInfo; |
19 | import org.h2.engine.Constants; |
20 | import org.h2.engine.Database; |
21 | import org.h2.engine.Session; |
22 | import org.h2.store.PageStore; |
23 | import org.h2.table.Table; |
24 | import org.h2.util.New; |
25 | |
26 | /** |
27 | * The MBean implementation. |
28 | * |
29 | * @author Eric Dong |
30 | * @author Thomas Mueller |
31 | */ |
32 | public class DatabaseInfo implements DatabaseInfoMBean { |
33 | |
34 | private static final Map<String, ObjectName> MBEANS = New.hashMap(); |
35 | |
36 | /** Database. */ |
37 | private final Database database; |
38 | |
39 | private DatabaseInfo(Database database) { |
40 | if (database == null) { |
41 | throw new IllegalArgumentException("Argument 'database' must not be null"); |
42 | } |
43 | this.database = database; |
44 | } |
45 | |
46 | /** |
47 | * Returns a JMX new ObjectName instance. |
48 | * |
49 | * @param name name of the MBean |
50 | * @param path the path |
51 | * @return a new ObjectName instance |
52 | * @throws JMException if the ObjectName could not be created |
53 | */ |
54 | private static ObjectName getObjectName(String name, String path) |
55 | throws JMException { |
56 | name = name.replace(':', '_'); |
57 | path = path.replace(':', '_'); |
58 | Hashtable<String, String> map = new Hashtable<String, String>(); |
59 | map.put("name", name); |
60 | map.put("path", path); |
61 | return new ObjectName("org.h2", map); |
62 | } |
63 | |
64 | /** |
65 | * Registers an MBean for the database. |
66 | * |
67 | * @param connectionInfo connection info |
68 | * @param database database |
69 | */ |
70 | public static void registerMBean(ConnectionInfo connectionInfo, |
71 | Database database) throws JMException { |
72 | String path = connectionInfo.getName(); |
73 | if (!MBEANS.containsKey(path)) { |
74 | MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); |
75 | String name = database.getShortName(); |
76 | ObjectName mbeanObjectName = getObjectName(name, path); |
77 | MBEANS.put(path, mbeanObjectName); |
78 | DatabaseInfo info = new DatabaseInfo(database); |
79 | Object mbean = new DocumentedMBean(info, DatabaseInfoMBean.class); |
80 | mbeanServer.registerMBean(mbean, mbeanObjectName); |
81 | } |
82 | } |
83 | |
84 | /** |
85 | * Unregisters the MBean for the database if one is registered. |
86 | * |
87 | * @param name database name |
88 | */ |
89 | public static void unregisterMBean(String name) throws Exception { |
90 | ObjectName mbeanObjectName = MBEANS.remove(name); |
91 | if (mbeanObjectName != null) { |
92 | MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); |
93 | mbeanServer.unregisterMBean(mbeanObjectName); |
94 | } |
95 | } |
96 | |
97 | @Override |
98 | public boolean isExclusive() { |
99 | return database.getExclusiveSession() != null; |
100 | } |
101 | |
102 | @Override |
103 | public boolean isReadOnly() { |
104 | return database.isReadOnly(); |
105 | } |
106 | |
107 | @Override |
108 | public String getMode() { |
109 | return database.getMode().getName(); |
110 | } |
111 | |
112 | @Override |
113 | public boolean isMultiThreaded() { |
114 | return database.isMultiThreaded(); |
115 | } |
116 | |
117 | @Override |
118 | public boolean isMvcc() { |
119 | return database.isMultiVersion(); |
120 | } |
121 | |
122 | @Override |
123 | public int getLogMode() { |
124 | return database.getLogMode(); |
125 | } |
126 | |
127 | @Override |
128 | public void setLogMode(int value) { |
129 | database.setLogMode(value); |
130 | } |
131 | |
132 | @Override |
133 | public int getTraceLevel() { |
134 | return database.getTraceSystem().getLevelFile(); |
135 | } |
136 | |
137 | @Override |
138 | public void setTraceLevel(int level) { |
139 | database.getTraceSystem().setLevelFile(level); |
140 | } |
141 | |
142 | @Override |
143 | public long getFileWriteCountTotal() { |
144 | if (!database.isPersistent()) { |
145 | return 0; |
146 | } |
147 | PageStore p = database.getPageStore(); |
148 | if (p != null) { |
149 | return p.getWriteCountTotal(); |
150 | } |
151 | // TODO remove this method when removing the page store |
152 | // (the MVStore doesn't support it) |
153 | return 0; |
154 | } |
155 | |
156 | @Override |
157 | public long getFileWriteCount() { |
158 | if (!database.isPersistent()) { |
159 | return 0; |
160 | } |
161 | PageStore p = database.getPageStore(); |
162 | if (p != null) { |
163 | return p.getWriteCount(); |
164 | } |
165 | return database.getMvStore().getStore().getFileStore().getReadCount(); |
166 | } |
167 | |
168 | @Override |
169 | public long getFileReadCount() { |
170 | if (!database.isPersistent()) { |
171 | return 0; |
172 | } |
173 | PageStore p = database.getPageStore(); |
174 | if (p != null) { |
175 | return p.getReadCount(); |
176 | } |
177 | return database.getMvStore().getStore().getFileStore().getReadCount(); |
178 | } |
179 | |
180 | @Override |
181 | public long getFileSize() { |
182 | if (!database.isPersistent()) { |
183 | return 0; |
184 | } |
185 | PageStore p = database.getPageStore(); |
186 | if (p != null) { |
187 | return p.getPageCount() * p.getPageSize() / 1024; |
188 | } |
189 | return database.getMvStore().getStore().getFileStore().size(); |
190 | } |
191 | |
192 | @Override |
193 | public int getCacheSizeMax() { |
194 | if (!database.isPersistent()) { |
195 | return 0; |
196 | } |
197 | PageStore p = database.getPageStore(); |
198 | if (p != null) { |
199 | return p.getCache().getMaxMemory(); |
200 | } |
201 | return database.getMvStore().getStore().getCacheSize() * 1024; |
202 | } |
203 | |
204 | @Override |
205 | public void setCacheSizeMax(int kb) { |
206 | if (database.isPersistent()) { |
207 | database.setCacheSize(kb); |
208 | } |
209 | } |
210 | |
211 | @Override |
212 | public int getCacheSize() { |
213 | if (!database.isPersistent()) { |
214 | return 0; |
215 | } |
216 | PageStore p = database.getPageStore(); |
217 | if (p != null) { |
218 | return p.getCache().getMemory(); |
219 | } |
220 | return database.getMvStore().getStore().getCacheSizeUsed() * 1024; |
221 | } |
222 | |
223 | @Override |
224 | public String getVersion() { |
225 | return Constants.getFullVersion(); |
226 | } |
227 | |
228 | @Override |
229 | public String listSettings() { |
230 | StringBuilder buff = new StringBuilder(); |
231 | for (Map.Entry<String, String> e : |
232 | new TreeMap<String, String>( |
233 | database.getSettings().getSettings()).entrySet()) { |
234 | buff.append(e.getKey()).append(" = ").append(e.getValue()).append('\n'); |
235 | } |
236 | return buff.toString(); |
237 | } |
238 | |
239 | @Override |
240 | public String listSessions() { |
241 | StringBuilder buff = new StringBuilder(); |
242 | for (Session session : database.getSessions(false)) { |
243 | buff.append("session id: ").append(session.getId()); |
244 | buff.append(" user: "). |
245 | append(session.getUser().getName()). |
246 | append('\n'); |
247 | buff.append("connected: "). |
248 | append(new Timestamp(session.getSessionStart())). |
249 | append('\n'); |
250 | Command command = session.getCurrentCommand(); |
251 | if (command != null) { |
252 | buff.append("statement: "). |
253 | append(session.getCurrentCommand()). |
254 | append('\n'); |
255 | long commandStart = session.getCurrentCommandStart(); |
256 | if (commandStart != 0) { |
257 | buff.append("started: ").append( |
258 | new Timestamp(commandStart)). |
259 | append('\n'); |
260 | } |
261 | } |
262 | Table[] t = session.getLocks(); |
263 | if (t.length > 0) { |
264 | for (Table table : session.getLocks()) { |
265 | if (table.isLockedExclusivelyBy(session)) { |
266 | buff.append("write lock on "); |
267 | } else { |
268 | buff.append("read lock on "); |
269 | } |
270 | buff.append(table.getSchema().getName()). |
271 | append('.').append(table.getName()). |
272 | append('\n'); |
273 | } |
274 | } |
275 | buff.append('\n'); |
276 | } |
277 | return buff.toString(); |
278 | } |
279 | |
280 | } |