* Note: Do not call this from within a synchronized block as it makes may send a JMX notification
*/
void attemptFullStart() throws Exception {
assert !Thread.holdsLock(this): "This method cannot be called while holding a synchronized lock on this";
State newState = null;
try {
synchronized (this) {
try {
// if we are still trying to start and can start now... start
if (getStateInstance() != State.STARTING) {
return;
}
// check if an mbean is blocking us from starting
blocker = dependencyManager.checkBlocker(objectName);
if (blocker != null) {
try {
// register for state change with the blocker
NotificationFilterSupport stoppedFilter = new NotificationFilterSupport();
stoppedFilter.enableType(NotificationType.STATE_STOPPED);
stoppedFilter.enableType(NotificationType.STATE_FAILED);
stoppedFilter.enableType(NotificationType.OBJECT_DELETED);
server.addNotificationListener(blocker, this, stoppedFilter, null);
// watch for the blocker to unregister
NotificationFilterSupport mbeanServerFilter = new NotificationFilterSupport();
mbeanServerFilter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
server.addNotificationListener(JMXUtil.DELEGATE_NAME, this, mbeanServerFilter, null);
// done for now... wait for the blocker to die
return;
} catch (InstanceNotFoundException e) {
// blocker died before we could get going... not a big deal
}
}
// check if all of the mbeans we depend on are running
Set parents = dependencyManager.getParents(objectName);
for (Iterator i = parents.iterator(); i.hasNext();) {
ObjectName parent = (ObjectName) i.next();
if (!server.isRegistered(parent)) {
log.trace("Cannot run because parent is not registered: parent=" + parent);
return;
}
try {
log.trace("Checking if parent is running: parent=" + parent);
if (((Integer) server.getAttribute(parent, "state")).intValue() != State.RUNNING_INDEX) {
log.trace("Cannot run because parent is not running: parent=" + parent);
return;
}
log.trace("Parent is running: parent=" + parent);
} catch (AttributeNotFoundException e) {
// ok -- parent is not a startable
log.trace("Parent does not have a State attibute");
} catch (InstanceNotFoundException e) {
// depended on instance was removed bewteen the register check and the invoke
log.trace("Cannot run because parent is not registered: parent=" + parent);
return;
} catch (Exception e) {
// problem getting the attribute, parent has most likely failed
log.trace("Cannot run because an error occurred while checking if parent is running: parent=" + parent);
return;
}
}
// remove any open watches on a blocker
// todo is this correct if we are returning to a waiting state?
if (blocker != null) {
// remove any open watches on a blocker
try {
server.removeNotificationListener(blocker, this);
} catch (JMException ignore) {
// don't care, just cleaning up... blocker is most likely dead
}
try {
server.removeNotificationListener(JMXUtil.DELEGATE_NAME, this);
} catch (JMException ignore) {
// this should never happen... maybe server is dead
}
blocker = null;
}
try {
doStart();
} catch (WaitingException e) {
log.debug("Waiting to start: objectName=\"" + objectName + "\" reason=\"" + e.getMessage() + "\"");
return;
}
setStateInstance(State.RUNNING);
newState = State.RUNNING;
} catch (Exception e) {
doSafeFail();
setStateInstance(State.FAILED);
newState = State.FAILED;
throw e;
} catch (Error e) {
doSafeFail();
setStateInstance(State.FAILED);
newState = State.FAILED;
throw e;
}
}
} finally {
if (newState != null) {
sendNotification(newState.getEventTypeValue());
}
}
}