/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* ident "%Z%%M% %I% %E% SMI"
*/
package com.sun.solaris.domain.pools;
import java.io.*;
import java.util.*;
import java.util.logging.*;
import java.text.DecimalFormat;
import java.util.concurrent.atomic.*;
import com.sun.solaris.service.locality.*;
import com.sun.solaris.service.logging.*;
import com.sun.solaris.service.pools.*;
import com.sun.solaris.service.exception.*;
/*
* poold overview
* ----- --------
*
* poold manipulates system resources in accordance with administrator
* specified constraints and objectives. The "goal" of the application
* is to maximise the efficiency of available resources within these
* parameters.
*
* Constraints are specified as follows:
*
* On a resource set:
*
* - min Is the minimum amount of resource a set should
* receive. poold will never elect to move resource so that a set
* falls below its minimum value. It is possible for a set to
* fall below its minimum as a consequence of administrative
* intervention, in which case poold will endeavour to bring a
* set back to its minimum level at the earliest opportunity.
*
* - max Is the maximum amount of resource a set should
* recieve. poold will never elect to move resource so that a set
* rises above its maximum value. It is possible for a set to
* rise above its maximum as a consequence of administrative
* intervention, in which case poold will endeavour to bring a
* set back to its maximum level at the earliest opportunity.
*
* On a resource component:
*
* - cpu.pinned Is an indication that a CPU should be ignored by
* poold for purposes of reallocation. A pinned CPU will never be
* moved by poold from one set to another.
*
* In addition to constraints, an administrator may also specify
* objectives. Currently three types of objectives are supported:
*
* - system.wt-load Is an objective set across an entire
* configuration. It attempts to ensure that resource is shared
* in accordance with current consumption. Those partitions which
* are most heavily utilized are give more resource in an attempt
* to lower their utilization levels.
*
* - set.locality Is a locality objective which attempts to
* minimize or maximize resource locality for a set.
*
* - set.utilization Is a utilization based objective which an
* administrator may use to explicitly dictate the utilization
* levels which should be achieved for a set.
*
* When executing, poold uses information about the current pools
* configuration; monitored resource utilization and specified
* constraints and objectives to determine if a move of resources is
* likely to lead to an increase in objective satisfaction.
*
* Candidate moves are generated by observing resource constraints.
* These moves are evaluated and scored in terms of their contribution
* to objective satisfaction (note: objectives are weighted according
* to their importance) and ranked accordingly. If a move can be
* identified that delivers an improvement, the move is made. Data is
* collected about past moves and recorded as "Decision History",
* before the move is made this data is consulted and if the move is
* expected not to yield an improvement, it may be cancelled. This
* refinement is designed to improve the quality of decision making by
* reflecting upon the past performance of decisions as well as the
* contribution to objective satisfaction.
*
* poold structure
* ----- ---------
*
* The common package name begins with:
*
* com.sun.solaris
*
* The software is divided into two main functional areas:
*
* service
*
* These packages collaborate to provide services to poold
* (typically, they use JNI to access exising
* functionality). They are not designed to be extended. For more
* details on these classes examine the source files in each
* directory.
*
* exception Stack trace formatter
* kstat Interface to Solaris kstat facility
* locality Interface to Solaris lgrp facility
* logging Interface to Solaris syslog facility
* pools Interface to Solaris libpool facility
* timer High resolution timestamps
*
* domain:
*
* These package reflect problem domain concepts and are
* responsible for application logic related to these
* concepts.
*
* pools Dynamic Resource Pools specific functionality.
*
* This code block will continue to explain in more detail how poold
* is organized.
*
* poold provides the following basic facilities:
*
* Monitoring:
*
* Basic statistic access is provided by the
* com.sun.solaris.service.kstat package. The following interfaces and
* classes collaborate to provide higher level statistic and
* monitoring facilities to the application:
*
* INTERFACES
*
* AggregateStatistic
* Monitor
* Statistic
* StatisticListener
*
* CLASSES
*
* AbstractStatistic
* DoubleStatistic
* LongStatistic
* ResourceMonitor
* StatisticEvent
* StatisticList
* StatisticOperations
* SystemMonitor
* UnsignedInt64Statistic
*
* Logging:
*
* Logging services are provided by the com.sun.solaris.logging
* package. In addition, the following class implements Poold's
* specific logging requirements.
*
* CLASSES
*
* Poold
*
* Optimization:
*
* lgrp service are provided by the com.sun.solaris.service.lgrp
* package. pools services are provided by the
* com.sun.solaris.service.pools package. In addition, optimization is
* implemented in the following Interfaces and Classes:
*
* INTERFACES
*
* Objective
* Solver
* WorkloadDependentObjective
*
* CLASSES
*
* AbstractObjective
* ComponentMove
* DecisionHistory
* Expression
* KExpression
* KVEpression
* KVOpExpression
* LocalityObjective
* Move
* Poold
* QuantityMove
* SystemSolver
* UtilizationObjective
* WeightedLoadObjective
*
* Configuration:
*
* pools services are provided by the com.sun.solaris.service.pools
* package, this is used to read poold configuration details from a
* libpool configuration. In addition, configuration is implemented in
* the following Classes:
*
* CLASSES
*
* AbstractObjective
* Expression
* Poold
* SystemSolver
*
* (NB: Some classes were mentioned in multiple categories where there
* responsbilities overlap. Inner classes are not listed as their
* responsibilities can be clearly inferred from their context.)
*
* For more details on any of the packages, classes or interfaces
* mentioned above, look at the documentation associated with each
* class.
*/
/**
* The <code>Poold</code> class implements a dynamic resource
* allocation system for Solaris.
*
* <code>Poold</code> is a monitoring daemon, designed to evaluate
* user specified objectives, monitor workload behaviour and
* dynamically assign resources in order to satisfy the evaluated
* objectives. For more details see:
*
* <a href="http://sac.eng.sun.com/PSARC/2002/287/">PSARC/2002/287</a>
*/
final class Poold
{
/**
* The configuration which is manipulated.
*/
private Configuration conf;
/**
* The monitoring interface.
*/
private Monitor monitor;
/**
* The interface to higher level resource managers.
*/
private DRM drm;
/**
* The interface to the configuration solver.
*/
private Solver solver;
/**
* Default path to the logging properties file.
*/
public static final String POOLD_PROPERTIES_PATH =
"/usr/lib/pool/poold.properties";
/**
* Logger for records which aren't produced in the Monitoring,
* Configuration, or Optimization states. This logger is the
* parent to the loggers used in those states.
*/
public static final Logger BASE_LOG = Logger.getLogger(
"com.sun.solaris.domain.pools.poold");
/**
* Logger for records produced in the Configuration state.
*/
public static final Logger CONF_LOG = Logger.getLogger(
"com.sun.solaris.domain.pools.poold.Configuration");
/**
* Logger for records produced in the Monitoring state.
*/
public static final Logger MON_LOG = Logger.getLogger(
"com.sun.solaris.domain.pools.poold.Monitoring");
/**
* Logger for records produced in the Optimization state.
*/
public static final Logger OPT_LOG = Logger.getLogger(
"com.sun.solaris.domain.pools.poold.Optimization");
/**
* Singleton instance of Poold.
*/
private static Poold instance;
/**
* The main sampling and solving thread.
*/
private Thread mainThread;
/**
* Process exit code indicating a failure.
*/
private static final int E_PO_FAILURE = 2;
/**
* Keep track of whether initialize() has been invoked, to
* output the "starting" message on the first.
*/
private AtomicBoolean firstInitialization = new AtomicBoolean(true);
/**
* Flags whether poold should run or exit.
*/
private AtomicBoolean shouldRun = new AtomicBoolean(true);
private static class logHelper {
/**
* Default logfile location
*/
public static final String DEF_LOG_LOC = "/var/log/pool/poold";
/**
* Log location indicating <code>syslog</code>, as
* opposed to a file, should be used.
*/
public static final String SYSLOG_LOG_LOC = "SYSLOG";
/**
* Default Log severity (if not overridden)
*/
public static final Severity DEF_SEVERITY = Severity.INFO;
/**
* Name of configuration property, log location.
*/
public static final String PROPERTY_NAME_LOG_LOC =
"system.poold.log-location";
/**
* Name of configuration property, log level.
*/
public static final String PROPERTY_NAME_LOG_LEVEL =
"system.poold.log-level";
/**
* Location of logfile -- an absolute filename, or
* "SYSLOG".
*/
private static String location;
/**
* Logfile handler, responsible for taking log messages
* and exporting them.
*/
private static Handler handler;
/**
* Logfile severity, log messages below this severity are
* ignored.
*/
private static Severity severity;
/**
* Flag recording whether preinitialization has occurred.
*/
private static boolean preinitialized = false;
/**
* Flag recording whether the logging Severity has been
* overridden with the -l command-line option, which
* means the console is the only thing being logged to,
* and the configuration's logging properties are
* ignored.
*/
private static boolean usingConsole;
/**
* Indicates whether logging semantics should be changed
* to facilitate debugging.
*/
private static final boolean loggingDebugging = false;
/**
* Do the pre-initialization initialization: install
* loggers for reporting errors during initialization.
*
* @param consoleSeverity If non-null, indicates that
* the configuration property-controlled logging behavior
* is to be overridden (the <code>-l</code> option was
* specified), and messages are to be logged only to the
* console, with (at most) the given maximum severity.
*/
private static void preinitialize(Severity consoleSeverity) {
if (preinitialized)
return;
/*
* Read logging properties affecting the
* FileHandler and ConsoleHandler from
* <code>poold.properties</code>.
*/
Properties props = new Properties();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
props.load(
new FileInputStream(POOLD_PROPERTIES_PATH));
props.store(bos, "");
LogManager.getLogManager().readConfiguration(
new ByteArrayInputStream(
bos.toByteArray()));
} catch (IOException ioe) {
Poold.MON_LOG.log(Severity.WARNING, "could not "
+ "read logging properties from "
+ "poold.properties: " + ioe);
}
if (consoleSeverity == null || loggingDebugging) {
/*
* Log messages to /var/log/pool/poold,
* the default location, until the pools
* configuration properties are read and
* applied, which may change the logging
* file and severity.
*
* Under normal circumstances, it's
* expected that NO INFO-level messages
* will be emitted until that time; this
* is only a measure to ensure that
* unanticipated errors are reported in
* some log.
*/
location = SYSLOG_LOG_LOC;
handler = SyslogHandler.getInstance("poold",
Facility.DAEMON);
severity = DEF_SEVERITY;
handler.setLevel(severity);
BASE_LOG.addHandler(handler);
}
if (consoleSeverity != null) {
/*
* If -l is specified, log to the
* console. Unless loggingDebug is
* true, this will also mean that the
* logging properties are ignored.
*
* Determine if the user has specified
* the use of a ConsoleHandler through
* poold.properties.
*/
Logger root = Logger.getLogger("");
Handler[] handler = root.getHandlers();
ConsoleHandler ch = null;
for (int i = 0; i < handler.length && ch ==
null; i++)
if (handler[i]
instanceof ConsoleHandler)
ch = (ConsoleHandler)handler[i];
/*
* If none was previously, install a
* ConsoleHandler.
*/
if (ch == null) {
ch = new ConsoleHandler();
ch.setFormatter(
new SysloglikeFormatter());
ch.setLevel(consoleSeverity);
root.addHandler(ch);
}
severity = consoleSeverity;
BASE_LOG.log(Severity.DEBUG,
"logging with level " + severity);
/**
* Allow logging properties to be
* effective if loggingDebugging is not
* set.
*/
if (!loggingDebugging)
usingConsole = true;
}
preinitialized = true;
}
/**
* Configure loggers based on the logging-related
* configuration properties. Outputs a description of
* any changes to the configuration logger.
*
* @throws ConfigurationException if there is an error
* applying libpool configuration properties to
* <code>poold</code>
*/
public static void initializeWithConfiguration(
Configuration conf) throws ConfigurationException
{
String newLogLocation;
Severity newLogSeverity;
String newLogSeverityName = null;
/*
* Set the log location as specified by the
* configuration's system properties.
*/
try {
newLogLocation = conf.getStringProperty(
PROPERTY_NAME_LOG_LOC);
} catch (PoolsException e) {
newLogLocation = DEF_LOG_LOC;
}
try {
newLogSeverityName = conf.getStringProperty(
PROPERTY_NAME_LOG_LEVEL);
newLogSeverity = Severity.getSeverityWithName(
newLogSeverityName);
assert(newLogSeverity != null);
} catch (PoolsException e) {
newLogSeverity = DEF_SEVERITY;
} catch (IllegalArgumentException e) {
throw(ConfigurationException)
(new ConfigurationException(
"invalid " + PROPERTY_NAME_LOG_LEVEL +
"value: " + newLogSeverityName)
.initCause(e));
}
Handler newLogHandler = null;
/*
* (Re)install the logger for the poold class
* hierarchy. This means that only poold
* messages are controlled by the pools
* configuration properties/command-line
* options.
*/
/*
* The logfile is always re-opened, in case the
* cause for reinitialization is due to SIGHUP
* following a log rotation.
*/
if (handler != null) {
BASE_LOG.removeHandler(handler);
handler.close();
handler = null;
}
if (newLogLocation.toUpperCase().equals(
SYSLOG_LOG_LOC.toUpperCase()))
newLogHandler =
SyslogHandler.getInstance("poold",
Facility.DAEMON);
else {
if (!newLogLocation.startsWith("/"))
throw
new ConfigurationException(
PROPERTY_NAME_LOG_LOC +
" value is not an" +
" absolute path");
try {
newLogHandler =
new FileHandler(
newLogLocation, 0, 1, true);
newLogHandler.setFormatter(
new SysloglikeFormatter());
} catch (java.io.IOException ioe) {
Poold.utility.die(
Poold.CONF_LOG,
new PooldException(
newLogLocation +
": can't write")
.initCause(ioe), false);
}
}
if (!severity.equals(newLogSeverity) ||
!location.equals(newLogLocation))
CONF_LOG.log(Severity.DEBUG,
"logging with level " + severity);
severity = newLogSeverity;
handler = newLogHandler;
location = newLogLocation;
handler.setLevel(severity);
BASE_LOG.addHandler(handler);
}
/**
* Configure the loggers based on the pool's logging
* properties, or, if the -l option was specified on the
* command line, continue to use the console.
*/
public static void initialize(Configuration conf)
throws ConfigurationException
{
if (usingConsole)
return;
else
initializeWithConfiguration(conf);
}
/**
* Return the current logging level.
*/
public static Severity getSeverity()
{
return (severity);
}
public static void close()
{
if (handler != null) {
BASE_LOG.removeHandler(handler);
handler.close();
}
}
}
/**
* Constructor
*
* Only one poold instance should be running per system.
*
* @param consoleSeverity If non-null, indicates that the
* configuration property-controlled logging behavior is to be
* overridden (the <code>-l</code> option was specified), and
* messages are to be logged only to the console, with (at most)
* the given maximum severity.
*/
private Poold(Severity consoleSeverity)
{
/*
* Establish loggers for recording errors during
* initialization. Under normal circumstances, no
* messages will be emitted; this is only a measure to
* make sure that unanticipated errors are reported in
* some log, or the console, if the -l option is used.
*/
logHelper.preinitialize(consoleSeverity);
/*
* Try opening the configuration read-write in hopes the
* ability will be possessed henceforth.
*/
try {
conf = new Configuration(PoolInternal.
pool_dynamic_location(), PoolInternal.PO_RDWR);
conf.close();
} catch (PoolsException pe) {
Poold.utility.die(CONF_LOG, new PooldException(
"cannot open dynamic pools configuration " +
"read-write (" + pe.getMessage() + ")")
.initCause(pe), false);
}
try {
conf = new Configuration(PoolInternal.
pool_dynamic_location(), PoolInternal.PO_RDONLY);
} catch (PoolsException pe) {
Poold.utility.die(CONF_LOG, pe);
}
/*
* Create the required sub-components:
* - a monitoring object
* - a DRM implementer
* - a solver
*/
monitor = new SystemMonitor();
drm = new LogDRM();
solver = new SystemSolver(monitor);
}
/**
* Returns a reference to the singleton <code>Poold</code>,
* constructing one if necessary.
*
* @param consoleSeverity If non-null, indicates that the
* configuration property-controlled logging behavior is to be
* overridden (the <code>-l</code> option was specified), and
* messages are to be logged only to the console, with (at most)
* the given maximum severity.
* @throws IllegalArgumentException if the given console
* severity doesn't match that of an existing instance.
*/
public static Poold getInstanceWithConsoleLogging(
Severity consoleSeverity)
{
if (instance == null)
return (instance = new Poold(consoleSeverity));
else
if (logHelper.usingConsole == false &&
consoleSeverity == null || consoleSeverity !=
null && logHelper.getSeverity().equals(
consoleSeverity))
return (instance);
else
throw new IllegalArgumentException();
}
/**
* Initializes <code>Poold</code> for operation at startup or
* in response to a detected libpool configuration change.
*/
private void initialize()
{
try {
logHelper.initialize(conf);
if (firstInitialization.get())
CONF_LOG.log(Severity.INFO, "starting");
/*
* When a system is extremely busy, it may
* prove difficult to initialize poold. Just
* keep trying until we succeed.
*/
boolean busy = true;
while (busy && shouldRun.get()) {
busy = false;
try {
monitor.initialize(conf);
CONF_LOG.log(Severity.DEBUG,
"configuring solver...");
solver.initialize(conf);
CONF_LOG.log(Severity.INFO,
"configuration complete");
} catch (PoolsException pe) {
CONF_LOG.log(Severity.INFO,
"The system is too busy to " +
"initialize, attempting " +
"initialization again");
/*
* pause for a while before
* re-attempting the
* initialization.
*/
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
/*
* Safe to ignore this
* exception as we
* will simply try
* again sooner.
*/
}
busy = true;
} catch (StaleMonitorException sme) {
CONF_LOG.log(Severity.INFO,
"The system is too busy to " +
"initialize, attempting " +
"initialization again");
/*
* pause for a while before
* re-attempting the
* initialization.
*/
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
/*
* Safe to ignore this
* exception as we
* will simply try
* again sooner.
*/
}
busy = true;
}
}
if (firstInitialization.get())
firstInitialization.set(false);
} catch (ConfigurationException ce) {
Poold.utility.die(CONF_LOG, ce);
}
}
/**
* Execute <code>Poold</code> indefinitely. This method is
* invoked after <code>Poold</code> completes
* configuration. It will continue to execute until
* <code>Poold</code> is terminated.
*
* @throws Exception If an there is an error in execution.
*/
private void execute() throws Exception
{
int changed = 0;
boolean confRequired = false;
while (shouldRun.get()) {
try {
changed = conf.update();
assert(!confRequired || confRequired &&
changed != 0);
if (changed != 0) {
CONF_LOG.log(Severity.DEBUG,
"configuration change detected");
if (!confRequired)
CONF_LOG.log(Severity.INFO,
"configuration changed " +
"externally");
CONF_LOG.log(Severity.INFO,
"reconfiguring...");
}
confRequired = false;
} catch (PoolsException pe) {
Poold.utility.die(CONF_LOG, pe);
}
if (changed != 0)
initialize();
boolean gotNext = false;
while (shouldRun.get() && !gotNext) {
try {
monitor.getNext();
gotNext = true;
/*
* All workload-dependent
* objectives must now be
* checked for violations. The
* solver holds all objectives
* and it makes the decision
* about whether a
* reconfiguration is required.
*/
if (solver.examine(monitor)) {
MON_LOG.log(Severity.INFO,
"reconfiguration required");
confRequired = solver.solve();
} else {
MON_LOG.log(Severity.INFO,
"all evaluated objectives"
+ " satisfied");
}
} catch (StaleMonitorException e) {
/*
* Later, assert that every
* cause of the
* StaleMonitorException is
* handled by the above
* conf.update().
*/
confRequired = true;
} catch (InterruptedException ie) {
Poold.MON_LOG.log(Severity.INFO,
"interrupted");
break;
}
}
if (!shouldRun.get())
break;
System.runFinalization();
}
Poold.BASE_LOG.log(Severity.NOTICE, "exiting");
}
/**
* Cleanup any resources when the application terminates.
*/
private void cleanup()
{
conf.close();
logHelper.close();
instance = null;
}
/**
* Invoke <code>Poold</code>. This main function is provided
* so that <code>poold</code> can be executed. Execution will
* continue indefinitely unless there is an error, in which case
* when execute() terminates.
*/
public void run()
{
mainThread = Thread.currentThread();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
cleanup();
} catch (Throwable t) {
}
}
});
try {
initialize();
execute();
} catch (Throwable t) {
Poold.utility.die(BASE_LOG, t);
}
}
/**
* Stops <code>Poold</code>. Sets a flag indicating that run()
* should break out of the monitor/solve loop and clean up.
*/
public void shutdown() {
/*
* Flag that the main thread should break out of the
* sample/solve loop as soon as possible.
*/
shouldRun.set(false);
/*
* Interrupt the main thread, which will cause the
* monitor to break out of its sleep if it's waiting for
* the sample time to arrive, and cause the sample/solve
* loop condition to be evaluated sooner. But make some
* effort not to cause an InterruptedIOException if
* we're not even through initialization yet; we'll get
* around to shutting down soon enough.
*/
if (!firstInitialization.get() && mainThread != null)
mainThread.interrupt();
}
public static void main(String args[]) throws IllegalArgumentException
{
Severity severity = null;
if (args.length > 0) {
if (args[0].compareTo("-l") == 0 && args.length == 2) {
severity = (Severity) Severity.parse(args[1]);
} else
throw new IllegalArgumentException(
"usage: poold [-l level]");
}
Poold p = getInstanceWithConsoleLogging(severity);
p.run();
}
/**
* The <code>utility</code> class provides various
* <code>Poold</code> related static utility methods that
* don't naturally reside on any class.
*/
static class utility {
/**
* Outputs a near-final message corresponding
* to an exception (or other throwable) to the named
* logger before causing the VM to exit. The message
* will have ERROR severity unless an instance of
* PoolsException is given, in which case the message
* will adopt the PoolsException's severity. Similarly,
* if the PoolsException specifies an exit code, it will
* be used; otherwise the default of
* <code>E_PO_FAILURE</code> will be used.
*
* @param logger Logger used to log the message
* @param t The cause. A stack trace will be affixed to
* the message.
*/
public static void die(Logger logger, Throwable t)
{
die(logger, t, true);
}
/**
* Outputs a near-final message corresponding
* to an exception (or other throwable) to the named
* logger before causing the VM to exit. The message
* will have ERROR severity unless an instance of
* PoolsException is given, in which case the message
* will adopt the PoolsException's severity. Similarly,
* if the PoolsException specifies an exit code, it will
* be used; otherwise the default of
* <code>E_PO_FAILURE</code> will be used.
*
* @param logger Logger used to log the message
* @param t The cause.
* @param showStackTrace If true, a stack trace will be
* affixed to the message.
*/
public static void die(Logger logger, Throwable t,
boolean showStackTrace)
{
try {
Severity severity;
/*
* Configure the message's exception and
* severity.
*/
LogRecord record;
if (t instanceof PooldException)
record = new LogRecord(
((PooldException)t).getSeverity(),
t.getMessage());
else
record = new LogRecord(Severity.ERR,
t.getMessage());
if (record.getMessage() == null)
record.setMessage("exception " +
t.getClass().getName());
if (showStackTrace)
record.setThrown(t);
record.setLoggerName(logger.getName());
logger.log(record);
if (logHelper.handler != null)
logHelper.handler.flush();
if (t instanceof PooldException)
System.exit(((PooldException)t)
.getExitCode());
else
System.exit(E_PO_FAILURE);
} catch (Exception e) {
SuccinctStackTraceFormatter.printStackTrace(e);
System.exit(-1);
}
}
/**
* Outputs a warning-level message to the named logger.
*
* @param logger Logger used to log the message
* @param t The cause.
* @param showStackTrace If true, a stack trace will be
* affixed to the message.
*/
public static void warn(Logger logger, Throwable t,
boolean showStackTrace)
{
try {
Severity severity;
/*
* Configure the message's exception and
* severity.
*/
LogRecord record;
if (t instanceof PooldException)
record = new LogRecord(
((PooldException)t).getSeverity(),
t.getMessage());
else
record = new LogRecord(Severity.WARNING,
t.getMessage());
if (record.getMessage() == null)
record.setMessage("exception " +
t.getClass().getName());
if (showStackTrace)
record.setThrown(t);
record.setLoggerName(logger.getName());
logger.log(record);
if (logHelper.handler != null)
logHelper.handler.flush();
} catch (Exception e) {
SuccinctStackTraceFormatter.printStackTrace(e);
System.exit(-1);
}
}
}
}
class ConfigurationException extends Exception
{
public ConfigurationException(String message)
{
super(message);
}
}
class IllegalOFValueException extends RuntimeException
{
public IllegalOFValueException(String message)
{
super(message);
}
}
class PooldException extends Exception {
/**
* The exit code which the virtual machine should exit at if
* this exception cannot be handled.
*/
private int exitCode;
/**
* The severity of this message. See <code>Severity</code>.
*/
private Severity severity;
/**
* Constructs a message with default exit code and
* <code>System.ERR</code> severity.
*/
public PooldException(String message)
{
this(message, 1, Severity.ERR);
}
/**
* Constructs a message with given exit code and
* <code>System.ERR</code> severity.
*/
public PooldException(String message, int exitCode)
{
this(message, exitCode, Severity.ERR);
}
/**
* Constructs a message with a given exit code and severity.
*/
public PooldException(String message, int exitCode, Severity severity)
{
super(message);
this.exitCode = exitCode;
this.severity = severity;
}
/**
* The exit code which the virtual machine should exit at if
* this exception cannot be handled.
*/
public int getExitCode()
{
return (exitCode);
}
public Severity getSeverity()
{
return (severity);
}
}