001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002-2005
005: * Sleepycat Software. All rights reserved.
006: *
007: * $Id: JEMBeanHelper.java 4644 2006-09-20 22:40:21Z paul_jack $
008: */
009:
010: package org.archive.util;
011:
012: import java.io.File;
013: import java.util.ArrayList;
014: import java.util.List;
015:
016: import javax.management.Attribute;
017: import javax.management.AttributeNotFoundException;
018: import javax.management.InvalidAttributeValueException;
019: import javax.management.MBeanAttributeInfo;
020: import javax.management.MBeanException;
021: import javax.management.MBeanNotificationInfo;
022: import javax.management.MBeanOperationInfo;
023: import javax.management.MBeanParameterInfo;
024:
025: import com.sleepycat.je.CheckpointConfig;
026: import com.sleepycat.je.Database;
027: import com.sleepycat.je.DatabaseConfig;
028: import com.sleepycat.je.DatabaseException;
029: import com.sleepycat.je.DatabaseStats;
030: import com.sleepycat.je.DbInternal;
031: import com.sleepycat.je.Environment;
032: import com.sleepycat.je.EnvironmentConfig;
033: import com.sleepycat.je.EnvironmentMutableConfig;
034: import com.sleepycat.je.StatsConfig;
035:
036: /**
037: * JEMBeanHelper is a utility class for the MBean implementation which wants to
038: * add management of a JE environment to its capabilities. MBean
039: * implementations can contain a JEMBeanHelper instance to get MBean metadata
040: * for JE and to set attributes, get attributes, and invoke operations.
041: * <p>
042: * com.sleepycat.je.jmx.JEMonitor and
043: * the example program jmx.JEApplicationMBean are two MBean implementations
044: * which provide support different application use cases. See those classes for
045: * examples of how to use JEMBeanHelper.
046: * <p>This class was copied from the bdb je 2.0 jmx examples.
047: */
048:
049: public class JEMBeanHelper {
050:
051: /*
052: * A note to JE developers: all available JE attributes and operations are
053: * described in the following static info arrays. New management
054: * functionality can be added to the helper by adding to the appropriate
055: * set of static definitions. For example, if we want to add a new JE
056: * attribute called "foo", which is available for open environments, we
057: * need to define a new MBeanAttributeInfo in the OPEN_ATTR array. The
058: * helper then needs to provide an implementation in set/getAttribute.
059: */
060:
061: /* --------------------- Attributes -------------------------- */
062:
063: /* Attribute names. */
064: public static final String ATT_ENV_HOME = "environmentHome";
065: public static final String ATT_OPEN = "isOpen";
066: public static final String ATT_IS_READ_ONLY = "isReadOnly";
067: public static final String ATT_IS_TRANSACTIONAL = "isTransactional";
068: public static final String ATT_CACHE_SIZE = "cacheSize";
069: public static final String ATT_CACHE_PERCENT = "cachePercent";
070: public static final String ATT_LOCK_TIMEOUT = "lockTimeout";
071: public static final String ATT_IS_SERIALIZABLE = "isSerializableIsolation";
072: public static final String ATT_TXN_TIMEOUT = "transactionTimeout";
073: public static final String ATT_SET_READ_ONLY = "openReadOnly";
074: public static final String ATT_SET_TRANSACTIONAL = "openTransactional";
075: public static final String ATT_SET_SERIALIZABLE = "openSerializableIsolation";
076:
077: /* COMMON_ATTR attributes are available for any environment. */
078: private static final MBeanAttributeInfo[] COMMON_ATTR = {
079:
080: new MBeanAttributeInfo(ATT_ENV_HOME, "java.lang.String",
081: "Environment home directory.", true, // readable
082: false, // writable
083: false), // isIs
084: new MBeanAttributeInfo(ATT_OPEN, "java.lang.Boolean",
085: "True if this environment is open.", true, // readable
086: false, // writable
087: true) // isIs
088: };
089:
090: /* OPEN_ATTR attributes are available for all open environments. */
091: private static final MBeanAttributeInfo[] OPEN_ATTR = {
092:
093: new MBeanAttributeInfo(ATT_IS_READ_ONLY,
094: "java.lang.Boolean",
095: "True if this environment is read only.", true, // readable
096: false, // writable
097: true), // isIs
098: new MBeanAttributeInfo(ATT_IS_TRANSACTIONAL,
099: "java.lang.Boolean",
100: "True if this environment supports transactions.",
101: true, // readable
102: false, // writable
103: true), // isIs
104: new MBeanAttributeInfo(ATT_CACHE_SIZE, "java.lang.Long",
105: "Cache size, in bytes.", true, // readable
106: true, // writable
107: false), // isIs
108: new MBeanAttributeInfo(
109: ATT_CACHE_PERCENT,
110: "java.lang.Integer",
111: "By default, cache size is (cachePercent * "
112: + "JVM maximum memory. To change the cache size "
113: + "using a percentage of the heap size, set "
114: + "the cache size to 0 and cachePercent to the "
115: + "desired percentage value.", true, // readable
116: true, // writable
117: false), // isIs
118: new MBeanAttributeInfo(ATT_LOCK_TIMEOUT, "java.lang.Long",
119: "Lock timeout, in microseconds.", true, // readable
120: false, // writable
121: false), // isIs
122: };
123:
124: /*
125: * TRANSACTIONAL_ATTR attributes are available only for open, transactional
126: * environments.
127: */
128: private static final MBeanAttributeInfo[] TRANSACTIONAL_ATTR = {
129:
130: new MBeanAttributeInfo(ATT_IS_SERIALIZABLE,
131: "java.lang.Boolean",
132: "True if this environment provides "
133: + "Serializable (degree 3) isolation. The "
134: + "default is RepeatableRead isolation.",
135: true, // readable
136: false, // writable
137: true), // isIs
138: new MBeanAttributeInfo(ATT_TXN_TIMEOUT, "java.lang.Long",
139: "Transaction timeout, in seconds. A value "
140: + "of 0 means there is no timeout.", true, // readable
141: false, // writable
142: false) // isIs
143: };
144:
145: /*
146: * CREATE_ATTR attributes are available when the mbean is configured to
147: * support configuration and opening by the mbean. They express the
148: * configuration settings.
149: */
150: private static final MBeanAttributeInfo[] CREATE_ATTR = {
151:
152: new MBeanAttributeInfo(ATT_SET_READ_ONLY,
153: "java.lang.Boolean",
154: "True if this environment should be opened "
155: + "in readonly mode.", true, // readable
156: true, // writable
157: false), // isIs
158: new MBeanAttributeInfo(ATT_SET_TRANSACTIONAL,
159: "java.lang.Boolean",
160: "True if this environment should be opened "
161: + "in transactional mode.", true, // readable
162: true, // writable
163: false), // isIs
164: new MBeanAttributeInfo(
165: ATT_SET_SERIALIZABLE,
166: "java.lang.Boolean",
167: "True if this environment should be opened "
168: + "with serializableIsolation. The default is "
169: + "false.", true, // readable
170: true, // writable
171: false), // isIs
172: };
173:
174: /* --------------------- Operations -------------------------- */
175:
176: /* Operation names */
177: static final String OP_CLEAN = "cleanLog";
178: static final String OP_EVICT = "evictMemory";
179: static final String OP_CHECKPOINT = "checkpoint";
180: static final String OP_SYNC = "sync";
181: static final String OP_ENV_STAT = "getEnvironmentStats";
182: static final String OP_ENV_STAT_STR = "getEnvironmentStatsToString";
183: static final String OP_LOCK_STAT = "getLockStats";
184: static final String OP_LOCK_STAT_STR = "getLockStatsToString";
185: static final String OP_TXN_STAT = "getTxnStats";
186: static final String OP_DB_NAMES = "getDatabaseNames";
187: static final String OP_DB_STAT = "getDatabaseStats";
188:
189: private static final MBeanOperationInfo OP_CLEAN_INFO = new MBeanOperationInfo(
190: OP_CLEAN, "Remove obsolete environment log files. "
191: + "Zero or more log files will be cleaned as "
192: + "necessary to bring the disk space "
193: + "utilization of the environment above the "
194: + "configured minimum utilization threshold "
195: + "as determined by the setting "
196: + "je.cleaner.minUtilization. Returns the "
197: + "number of files cleaned, that will be "
198: + "deleted at the next qualifying checkpoint.",
199: new MBeanParameterInfo[0], // no params
200: "java.lang.Integer", MBeanOperationInfo.UNKNOWN);
201:
202: private static final MBeanOperationInfo OP_EVICT_INFO = new MBeanOperationInfo(
203: OP_EVICT, "Reduce cache usage to the threshold "
204: + "determined by the setting "
205: + "je.evictor.useMemoryFloor. ",
206: new MBeanParameterInfo[0], // no params
207: "void", MBeanOperationInfo.UNKNOWN);
208:
209: /* parameter for checkpoint operation. */
210: private static final MBeanParameterInfo[] checkpointParams = { new MBeanParameterInfo(
211: "force", "java.lang.Boolean",
212: "If true, force a checkpoint even if "
213: + "there has been no activity since the last "
214: + "checkpoint. Returns true if a checkpoint "
215: + "executed.") };
216:
217: private static final MBeanOperationInfo OP_CHECKPOINT_INFO = new MBeanOperationInfo(
218: OP_CHECKPOINT, "Checkpoint the environment.",
219: checkpointParams, "void", MBeanOperationInfo.UNKNOWN);
220:
221: private static final MBeanOperationInfo OP_SYNC_INFO = new MBeanOperationInfo(
222: OP_SYNC, "Flush the environment to stable storage.",
223: new MBeanParameterInfo[0], // no params
224: "void", MBeanOperationInfo.UNKNOWN);
225:
226: private static final MBeanParameterInfo[] statParams = {
227: new MBeanParameterInfo("clear", "java.lang.Boolean",
228: "If true, reset statistics after reading."),
229: new MBeanParameterInfo("fast", "java.lang.Boolean",
230: "If true, only return statistics which do "
231: + "not require expensive computation.")
232:
233: };
234:
235: private static final MBeanOperationInfo OP_ENV_STAT_INFO = new MBeanOperationInfo(
236: OP_ENV_STAT, "Get environment statistics.", statParams,
237: "com.sleepycat.je.EnvironmentStats",
238: MBeanOperationInfo.INFO);
239:
240: private static final MBeanOperationInfo OP_ENV_STAT_STR_INFO = new MBeanOperationInfo(
241: OP_ENV_STAT_STR, "Get environment statistics.", statParams,
242: "java.lang.String", MBeanOperationInfo.INFO);
243:
244: private static final MBeanOperationInfo OP_LOCK_STAT_INFO = new MBeanOperationInfo(
245: OP_LOCK_STAT, "Get locking statistics.", statParams,
246: "com.sleepycat.je.LockStats", MBeanOperationInfo.INFO);
247:
248: private static final MBeanOperationInfo OP_LOCK_STAT_STR_INFO = new MBeanOperationInfo(
249: OP_LOCK_STAT_STR, "Get locking statistics.", statParams,
250: "java.lang.String", MBeanOperationInfo.INFO);
251:
252: private static final MBeanOperationInfo OP_TXN_STAT_INFO = new MBeanOperationInfo(
253: OP_TXN_STAT, "Get transactional statistics.", statParams,
254: "com.sleepycat.je.TransactionStats",
255: MBeanOperationInfo.INFO);
256:
257: private static final MBeanOperationInfo OP_DB_NAMES_INFO = new MBeanOperationInfo(
258: OP_DB_NAMES,
259: "Get the names of databases in the environment.",
260: new MBeanParameterInfo[0], // no params
261: "java.lang.String", MBeanOperationInfo.INFO);
262:
263: private static final MBeanOperationInfo OP_DB_STAT_INFO = new MBeanOperationInfo(
264: OP_DB_STAT, "Get database statistics.", statParams,
265: "com.sleepycat.je.TransactionStats",
266: MBeanOperationInfo.INFO);
267: /*
268: private static final MBeanParameterInfo [] dbStatParams = {
269: new MBeanParameterInfo ("clear", "java.lang.Boolean",
270: "If true, reset statistics after reading."),
271: new MBeanParameterInfo ("fast", "java.lang.Boolean",
272: "If true, only return statistics which do " +
273: "not require expensive computation."),
274: new MBeanParameterInfo ("databaseName", "java.lang.String",
275: "database name")
276:
277: };
278: */
279: /* target JE environment home directory. */
280: private File environmentHome;
281:
282: /*
283: * If canConfigure is true, this helper will make environment configuration
284: * attributes available in the mbean metadata. Configuration attributes
285: * will be saved in the openConfig instance.
286: */
287: private boolean canConfigure;
288: private EnvironmentConfig openConfig;
289:
290: /* true if the mbean metadata needs to be refreshed. */
291: private boolean needReset;
292:
293: /*
294: * Save whether the environment was open the last time we fetched
295: * mbean attributes. Use to detect a change in environment status.
296: */
297: private boolean envWasOpen;
298:
299: /**
300: * Instantiate a helper, specifying environment home and open capabilities.
301: *
302: * @param environmentHome home directory of the target JE environment.
303: * @param canConfigure If true, the helper will show environment
304: * configuration attributes.
305: */
306: public JEMBeanHelper(EnvironmentConfig config,
307: File environmentHome, boolean canConfigure) {
308:
309: if (environmentHome == null) {
310: throw new IllegalArgumentException(
311: "Environment home cannot be null");
312: }
313: this .environmentHome = environmentHome;
314: this .canConfigure = canConfigure;
315: if (canConfigure) {
316: openConfig = config;
317: }
318: }
319:
320: /**
321: * Return the target environment directory.
322: * @return the environment directory.
323: */
324: public File getEnvironmentHome() {
325: return environmentHome;
326: }
327:
328: /**
329: * If the helper was instantiated with canConfigure==true, it shows
330: * environment configuration attributes. Those attributes are returned
331: * within this EnvironmentConfig object for use in opening environments.
332: *
333: * @return EnvironmentConfig object which saves configuration attributes
334: * recorded through MBean attributes.
335: */
336: public EnvironmentConfig getEnvironmentOpenConfig() {
337: return openConfig;
338: }
339:
340: /**
341: * Return an Environment only if the environment has already been opened
342: * in this process. A helper method for MBeans which want to only access
343: * open environments.
344: * @return Environment if already open, null if not open.
345: */
346: public Environment getEnvironmentIfOpen() {
347: if (environmentHome == null) {
348: return null;
349: }
350:
351: return DbInternal.getEnvironmentShell(environmentHome);
352: }
353:
354: /**
355: * Tell the MBean if the available set of functionality has changed.
356: *
357: * @return true if the MBean should regenerate its JE metadata.
358: */
359: public synchronized boolean getNeedReset() {
360: return needReset;
361: }
362:
363: /********************************************************************/
364: /* MBean Attributes */
365: /********************************************************************/
366:
367: /**
368: * Get MBean attribute metadata for this environment.
369: * @param targetEnv The target JE environment. May be null if the
370: * environment is not open.
371: * @return list of MBeanAttributeInfo objects describing the available
372: * attributes.
373: */
374: public List<MBeanAttributeInfo> getAttributeList(
375: Environment targetEnv) {
376:
377: /* Turn off reset because the mbean metadata is being refreshed. */
378: setNeedReset(false);
379:
380: ArrayList<MBeanAttributeInfo> attrList = new ArrayList<MBeanAttributeInfo>();
381:
382: /* Add attributes for all JE environments. */
383: for (int i = 0; i < COMMON_ATTR.length; i++) {
384: attrList.add(COMMON_ATTR[i]);
385: }
386:
387: if (targetEnv == null) {
388: if (canConfigure) {
389: /* Add attributes for configuring an environment. */
390: for (int i = 0; i < CREATE_ATTR.length; i++) {
391: attrList.add(CREATE_ATTR[i]);
392: }
393: }
394: } else {
395: /* Add attributes for an open environment. */
396: for (int i = 0; i < OPEN_ATTR.length; i++) {
397: attrList.add(OPEN_ATTR[i]);
398: }
399:
400: /* Add attributes for an open, transactional environment. */
401: try {
402: EnvironmentConfig config = targetEnv.getConfig();
403: if (config.getTransactional()) {
404: for (int i = 0; i < TRANSACTIONAL_ATTR.length; i++) {
405: attrList.add(TRANSACTIONAL_ATTR[i]);
406: }
407: }
408: } catch (DatabaseException ignore) {
409: /* ignore */
410: }
411: }
412:
413: return attrList;
414: }
415:
416: /**
417: * Get an attribute value for the given environment. Check
418: * JEMBeanHelper.getNeedReset() after this call because the helper may
419: * detect that the environment has changed and that the MBean metadata
420: * should be reset.
421: *
422: * @param targetEnv The target JE environment. May be null if the
423: * environment is not open.
424: * @param attributeName attribute name.
425: * @return attribute value.
426: */
427: public Object getAttribute(Environment targetEnv,
428: String attributeName) throws AttributeNotFoundException,
429: MBeanException {
430:
431: /* Sanity check. */
432: if (attributeName == null) {
433: throw new AttributeNotFoundException(
434: "Attribute name cannot be null");
435: }
436:
437: /* These attributes are available regardless of environment state. */
438: try {
439: if (attributeName.equals(ATT_ENV_HOME)) {
440: return environmentHome.getCanonicalPath();
441: } else if (attributeName.equals(ATT_OPEN)) {
442: boolean envIsOpen = (targetEnv != null);
443: resetIfOpenStateChanged(envIsOpen);
444: return new Boolean(envIsOpen);
445: } else if (attributeName.equals(ATT_SET_READ_ONLY)) {
446: return new Boolean(openConfig.getReadOnly());
447: } else if (attributeName.equals(ATT_SET_TRANSACTIONAL)) {
448: return new Boolean(openConfig.getTransactional());
449: } else if (attributeName.equals(ATT_SET_SERIALIZABLE)) {
450: return new Boolean(openConfig
451: .getTxnSerializableIsolation());
452: } else {
453: /* The rest are JE environment attributes. */
454: if (targetEnv != null) {
455:
456: EnvironmentConfig config = targetEnv.getConfig();
457:
458: if (attributeName.equals(ATT_IS_READ_ONLY)) {
459: return new Boolean(config.getReadOnly());
460: } else if (attributeName
461: .equals(ATT_IS_TRANSACTIONAL)) {
462: return new Boolean(config.getTransactional());
463: } else if (attributeName.equals(ATT_CACHE_SIZE)) {
464: return new Long(config.getCacheSize());
465: } else if (attributeName.equals(ATT_CACHE_PERCENT)) {
466: return new Integer(config.getCachePercent());
467: } else if (attributeName.equals(ATT_LOCK_TIMEOUT)) {
468: return new Long(config.getLockTimeout());
469: } else if (attributeName
470: .equals(ATT_IS_SERIALIZABLE)) {
471: return new Boolean(config
472: .getTxnSerializableIsolation());
473: } else if (attributeName.equals(ATT_TXN_TIMEOUT)) {
474: return new Long(config.getTxnTimeout());
475: } else {
476: throw new AttributeNotFoundException(
477: "attribute " + attributeName
478: + " is not valid.");
479: }
480: }
481: return null;
482: }
483: } catch (Exception e) {
484: /*
485: * Add both the message and the exception for easiest deciphering
486: * of the problem. Sometimes the original exception stacktrace gets
487: * hidden in server logs.
488: */
489: throw new MBeanException(e, e.getMessage());
490: }
491: }
492:
493: /**
494: * Set an attribute value for the given environment.
495: *
496: * @param targetEnv The target JE environment. May be null if the
497: * environment is not open.
498: * @param attribute name/value pair
499: */
500: public void setAttribute(Environment targetEnv, Attribute attribute)
501: throws AttributeNotFoundException,
502: InvalidAttributeValueException {
503:
504: if (attribute == null) {
505: throw new AttributeNotFoundException(
506: "Attribute cannot be null");
507: }
508:
509: /* Sanity check parameters. */
510: String name = attribute.getName();
511: Object value = attribute.getValue();
512:
513: if (name == null) {
514: throw new AttributeNotFoundException(
515: "Attribute name cannot be null");
516: }
517:
518: if (value == null) {
519: throw new InvalidAttributeValueException(
520: "Attribute value for attribute " + name
521: + " cannot be null");
522: }
523:
524: try {
525: if (name.equals(ATT_SET_READ_ONLY)) {
526: openConfig
527: .setReadOnly(((Boolean) value).booleanValue());
528: } else if (name.equals(ATT_SET_TRANSACTIONAL)) {
529: openConfig.setTransactional(((Boolean) value)
530: .booleanValue());
531: } else if (name.equals(ATT_SET_SERIALIZABLE)) {
532: openConfig
533: .setTxnSerializableIsolation(((Boolean) value)
534: .booleanValue());
535: } else {
536: /* Set the specified attribute if the environment is open. */
537: if (targetEnv != null) {
538:
539: EnvironmentMutableConfig config = targetEnv
540: .getMutableConfig();
541:
542: if (name.equals(ATT_CACHE_SIZE)) {
543: config.setCacheSize(((Long) value).longValue());
544: targetEnv.setMutableConfig(config);
545: } else if (name.equals(ATT_CACHE_PERCENT)) {
546: config.setCachePercent(((Integer) value)
547: .intValue());
548: targetEnv.setMutableConfig(config);
549: } else {
550: throw new AttributeNotFoundException(
551: "attribute " + name + " is not valid.");
552: }
553: } else {
554: throw new AttributeNotFoundException("attribute "
555: + name + " is not valid.");
556: }
557: }
558: } catch (NumberFormatException e) {
559: throw new InvalidAttributeValueException("attribute name="
560: + name);
561: } catch (DatabaseException e) {
562: throw new InvalidAttributeValueException("attribute name="
563: + name + e.getMessage());
564: }
565: }
566:
567: /********************************************************************/
568: /* JE Operations */
569: /********************************************************************/
570:
571: /**
572: * Get mbean operation metadata for this environment.
573: *
574: * @param targetEnv The target JE environment. May be null if the
575: * environment is not open.
576: * @return List of MBeanOperationInfo describing available operations.
577: */
578: public List<MBeanOperationInfo> getOperationList(
579: Environment targetEnv) {
580: setNeedReset(false);
581:
582: List<MBeanOperationInfo> operationList = new ArrayList<MBeanOperationInfo>();
583:
584: if (targetEnv != null) {
585: /*
586: * These operations are only available if the environment is
587: * open.
588: */
589: operationList.add(OP_CLEAN_INFO);
590: operationList.add(OP_EVICT_INFO);
591: operationList.add(OP_ENV_STAT_INFO);
592: operationList.add(OP_ENV_STAT_STR_INFO);
593: operationList.add(OP_LOCK_STAT_INFO);
594: operationList.add(OP_LOCK_STAT_STR_INFO);
595: operationList.add(OP_DB_NAMES_INFO);
596: operationList.add(OP_DB_STAT_INFO);
597:
598: /* Add checkpoint only for transactional environments. */
599: boolean isTransactional = false;
600: try {
601: EnvironmentConfig config = targetEnv.getConfig();
602: isTransactional = config.getTransactional();
603: } catch (DatabaseException e) {
604: /* Don't make any operations available. */
605: return new ArrayList<MBeanOperationInfo>();
606: }
607:
608: if (isTransactional) {
609: operationList.add(OP_CHECKPOINT_INFO);
610: operationList.add(OP_TXN_STAT_INFO);
611: } else {
612: operationList.add(OP_SYNC_INFO);
613: }
614: }
615:
616: return operationList;
617: }
618:
619: /**
620: * Invoke an operation for the given environment.
621: *
622: * @param targetEnv The target JE environment. May be null if the
623: * environment is not open.
624: * @param actionName operation name.
625: * @param params operation parameters. May be null.
626: * @param signature operation signature. May be null.
627: * @return the operation result
628: */
629: public Object invoke(Environment targetEnv, String actionName,
630: Object[] params, String[] signature) throws MBeanException {
631:
632: /* Sanity checking. */
633: if (actionName == null) {
634: throw new IllegalArgumentException(
635: "actionName cannot be null");
636: }
637:
638: try {
639: if (targetEnv != null) {
640: if (actionName.equals(OP_CLEAN)) {
641: int numFiles = targetEnv.cleanLog();
642: return new Integer(numFiles);
643: } else if (actionName.equals(OP_EVICT)) {
644: targetEnv.evictMemory();
645: return null;
646: } else if (actionName.equals(OP_CHECKPOINT)) {
647: CheckpointConfig config = new CheckpointConfig();
648: if ((params != null) && (params.length > 0)) {
649: Boolean force = (Boolean) params[0];
650: config.setForce(force.booleanValue());
651: }
652: targetEnv.checkpoint(config);
653: return null;
654: } else if (actionName.equals(OP_SYNC)) {
655: targetEnv.sync();
656: return null;
657: } else if (actionName.equals(OP_ENV_STAT)) {
658: return targetEnv.getStats(getStatsConfig(params));
659: } else if (actionName.equals(OP_ENV_STAT_STR)) {
660: return targetEnv.getStats(getStatsConfig(params))
661: .toString();
662: } else if (actionName.equals(OP_LOCK_STAT)) {
663: return targetEnv
664: .getLockStats(getStatsConfig(params));
665: } else if (actionName.equals(OP_LOCK_STAT_STR)) {
666: return targetEnv.getLockStats(
667: getStatsConfig(params)).toString();
668: } else if (actionName.equals(OP_TXN_STAT)) {
669: return targetEnv
670: .getTransactionStats(getStatsConfig(params));
671: } else if (actionName.equals(OP_DB_NAMES)) {
672: return targetEnv.getDatabaseNames();
673: } else if (actionName.equals(OP_DB_STAT)) {
674: return getDatabaseStats(targetEnv, params);
675: }
676: }
677:
678: return new IllegalArgumentException("actionName: "
679: + actionName + " is not valid");
680: } catch (DatabaseException e) {
681: /*
682: * Add both the message and the exception for easiest
683: * deciphering of the problem. Sometimes the original exception
684: * stacktrace gets hidden in server logs.
685: */
686: throw new MBeanException(e, e.getMessage());
687: }
688: }
689:
690: /**
691: * Helper for creating a StatsConfig object to use as an operation
692: * parameter.
693: */
694: private StatsConfig getStatsConfig(Object[] params) {
695: StatsConfig statsConfig = new StatsConfig();
696: if ((params != null) && (params.length > 0)
697: && (params[0] != null)) {
698: Boolean clear = (Boolean) params[0];
699: statsConfig.setClear(clear.booleanValue());
700: }
701: if ((params != null) && (params.length > 1)
702: && (params[1] != null)) {
703: Boolean fast = (Boolean) params[1];
704: statsConfig.setFast(fast.booleanValue());
705: }
706: return statsConfig;
707: }
708:
709: /**
710: * Helper to get statistics for a given database.
711: * @param params operation parameters
712: * @return DatabaseStats object
713: */
714: private DatabaseStats getDatabaseStats(Environment targetEnv,
715: Object[] params) throws IllegalArgumentException,
716: DatabaseException {
717:
718: if ((params == null) || (params.length < 3)) {
719: return null;
720: }
721: String dbName = (String) params[2];
722:
723: Database db = null;
724: try {
725: DatabaseConfig dbConfig = new DatabaseConfig();
726: dbConfig.setReadOnly(true);
727: DbInternal.setUseExistingConfig(dbConfig, true);
728: db = targetEnv.openDatabase(null, dbName, dbConfig);
729: return db.getStats(getStatsConfig(params));
730: } finally {
731: if (db != null) {
732: db.close();
733: }
734: }
735: }
736:
737: /********************************************************************/
738: /* JE Notifications.
739: /********************************************************************/
740:
741: /**
742: * No notifications are supported.
743: * @return List of MBeanNotificationInfo for available notifications.
744: */
745: public MBeanNotificationInfo[] getNotificationInfo(
746: Environment targetEnv) {
747: return null;
748: }
749:
750: /********************************************************************/
751: /* private helpers.
752: /********************************************************************/
753:
754: private synchronized void setNeedReset(boolean reset) {
755: needReset = reset;
756: }
757:
758: private synchronized void resetIfOpenStateChanged(boolean isOpen) {
759: if (isOpen != envWasOpen) {
760: setNeedReset(true);
761: envWasOpen = isOpen;
762: }
763: }
764: }
|