use of alma.maciErrType.wrappers.AcsJComponentDeactivationUncleanEx in project ACS by ACS-Community.
the class ComponentAdapter method deactivateComponent.
/**
* Deactivates a component.
* <ol>
* <li>First the component's POA manager is put into inactive state, so that all incoming calls to this component are rejected.
* However, we wait for currently executing calls to finish, with a timeout as described below.
* <ul>
* <li>Rejection applies to requests already received and queued by the ORB (but that have not started executing),
* as well as to requests that clients will send in the future.
* <li>Note that entering into the inactive state may take forever if the component hangs in a functional call.
* <li>Therefore we use a timeout to proceed in such cases where POA manager deactivation does not happen in time.
* This bears the risk of undesirable behavior caused by calling the {@link ComponentLifecycle#cleanUp() cleanUp}
* method while other threads still perform functional calls on the component.
* </ul>
* <li>Second the component itself is deactivated:
* <ul>
* <li>The lifecycle method {@link ComponentLifecycle#cleanUp() cleanUp} is called, currently without enforcing a timeout.
* <li>TODO: use a timeout, unless we decide that a client-side timeout for releaseComponent is good enough.
* </ul>
* <li>Third the component is disconnected from CORBA ("etherealized" from the POA).
* <ul>
* <li>Note that also etherealization may take forever if the component hangs in a call.
* <li>Therefore we use a timeout to proceed with deactivation in such cases where etherealization does not happen in time.
* <li>Currently a component that failed to etherealize in time can stay active as long as the container is alive.
* TODO: check if using the "container sealant" we can identify and stop the active ORB threads.
* </ul>
* </ol>
* This method logs errors as FINER if they also cause an exception, and as WARNING if they cannot lead to an exception
* because other more important error conditions are present.
*
* @throws ComponentDeactivationUncleanEx, ComponentDeactivationFailedEx
*/
void deactivateComponent() throws AcsJComponentDeactivationUncleanEx, AcsJComponentDeactivationFailedEx {
if (m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.finer("About to deactivate component " + m_compInstanceName + " with handle " + getHandle());
}
AcsJComponentDeactivationUncleanEx deactivationUncleanEx = null;
AcsJComponentDeactivationFailedEx deactivationFailedEx = null;
try {
// (1) try to reject calls by sending poa manager to inactive state
// TODO: make the timeout configurable
int deactivateTimeoutMillis = 10000;
boolean isInactive = acsCorba.deactivateComponentPOAManager(m_componentPOA, m_compInstanceName, deactivateTimeoutMillis);
if (isInactive && m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.finer("Now rejecting any calls to component '" + m_compInstanceName + "'. Will call cleanUp() next.");
} else if (!isInactive) {
String msg = "Component '" + m_compInstanceName + "' failed to reject calls within " + deactivateTimeoutMillis + " ms, probably because of pending calls. Will call cleanUp() anyway.";
m_containerLogger.warning(msg);
deactivationUncleanEx = new AcsJComponentDeactivationUncleanEx();
deactivationUncleanEx.setCURL(m_compInstanceName);
deactivationUncleanEx.setReason(msg);
// do not yet throw deactivationUncleanEx as we need to go through the other steps first
}
// (2) call the lifecycle method cleanUp and also clean container services and other support classes
ClassLoader contCL = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(m_componentClassLoader);
try {
// TODO: also use a timeout for cleanUp
m_component.cleanUp();
} catch (Throwable thr) {
// AcsJComponentCleanUpEx is declared, but any other ex will be wrapped by AcsJComponentDeactivationUncleanEx as well
m_containerLogger.log(Level.FINE, "Failure in cleanUp() method of component " + m_compInstanceName, thr);
// this would override a previous ex from POA deactivation
deactivationUncleanEx = new AcsJComponentDeactivationUncleanEx(thr);
deactivationUncleanEx.setCURL(m_compInstanceName);
// do not yet throw deactivationUncleanEx as we need to nonetheless destroy the POA
} finally {
Thread.currentThread().setContextClassLoader(contCL);
try {
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_DEFUNCT);
} catch (ComponentLifecycleException ex) {
if (deactivationUncleanEx == null) {
// an ex from cleanUp would be more important
deactivationUncleanEx = new AcsJComponentDeactivationUncleanEx(ex);
deactivationUncleanEx.setCURL(m_compInstanceName);
} else {
m_containerLogger.log(Level.WARNING, "Failed to set component state DEFUNCT on " + m_compInstanceName, ex);
}
}
m_containerServices.cleanUp();
m_threadFactory.cleanUp();
}
// (3) destroy the component POA
// since we already tried to discard requests using the poa manager before,
// the additional timeout can be kept small. If calls are pending, we fail.
int etherealizeTimeoutMillis = 1000;
boolean isEtherealized = acsCorba.destroyComponentPOA(m_componentPOA, compServantManager, etherealizeTimeoutMillis);
if (isEtherealized && m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.finer("Component '" + m_compInstanceName + "' is etherealized.");
} else if (!isEtherealized) {
m_containerLogger.warning("Component '" + m_compInstanceName + "' failed to be etherealized in " + etherealizeTimeoutMillis + " ms, probably because of pending calls.");
deactivationFailedEx = new AcsJComponentDeactivationFailedEx();
deactivationFailedEx.setCURL(m_compInstanceName);
deactivationFailedEx.setReason("Component POA etherialization timed out after " + etherealizeTimeoutMillis + " ms.");
// @TODO: distinguish the cases better
deactivationFailedEx.setIsPermanentFailure(true);
// do not yet throw deactivationFailedEx as we need to nonetheless close the classloader
}
// (4) "close" m_componentClassLoader (otherwise JVM native mem leak, see COMP-4929)
if (m_componentClassLoader instanceof AcsComponentClassLoader) {
try {
((AcsComponentClassLoader) m_componentClassLoader).close();
} catch (IOException ex) {
m_containerLogger.log(Level.WARNING, "Failed to close component class loader", ex);
}
}
} catch (RuntimeException ex) {
if (deactivationFailedEx == null) {
// exception from POA destruction has precedence
deactivationFailedEx = new AcsJComponentDeactivationFailedEx(ex);
deactivationFailedEx.setCURL(m_compInstanceName);
deactivationFailedEx.setReason("Unexpected exception caught during component deactivation.");
} else {
m_containerLogger.log(Level.WARNING, "Unexpected exception caught during deactivation of component " + m_compInstanceName, ex);
}
}
if (deactivationFailedEx != null) {
if (m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.log(Level.FINER, "Deactivation of component " + m_compInstanceName + " failed. " + "Will throw AcsJComponentDeactivationFailedEx", deactivationFailedEx);
}
throw deactivationFailedEx;
}
if (deactivationUncleanEx != null) {
if (m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.log(Level.FINER, "Deactivation of component " + m_compInstanceName + " finished with problems. " + "Will throw AcsJComponentDeactivationUncleanEx", deactivationUncleanEx);
}
throw deactivationUncleanEx;
}
if (m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.finer("Done deactivating component " + m_compInstanceName + " with handle " + getHandle());
}
}
Aggregations