use of com.cosylab.acs.maci.manager.recovery.ContainerInfoCommandComponentRemove in project ACS by ACS-Community.
the class ManagerImpl method containerPostLoginActivation.
/**
* Container post login activation, activate startup and unavailable components.
* NOTE: to be run in separate thread.
*
* @param containerInfo container info for which to perform post login activation.
* @param recoverContainer recovery mode flag.
*/
private void containerPostLoginActivation(final ContainerInfo containerInfo, boolean recoverContainer) {
// give containers some time to fully initialize
if (containerInfo.getImplLang() == ImplLang.cpp || containerInfo.getImplLang() == ImplLang.not_specified) {
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {
}
}
// shutdown check
if (isShuttingDown())
return;
// CDB startup
if (cdbActivation != null && containerInfo.getName().equals(cdbActivation.getContainer())) {
try {
StatusHolder status = new StatusHolder();
ComponentInfo cdbInfo = internalRequestComponent(this.getHandle(), cdbActivation.getName(), cdbActivation.getType(), cdbActivation.getCode(), cdbActivation.getContainer(), RELEASE_IMMEDIATELY, status, true);
if (status.getStatus() != ComponentStatus.COMPONENT_ACTIVATED)
logger.log(Level.SEVERE, "Failed to activate CDB, reason: '" + status.getStatus() + "'.");
else if (cdbInfo == null || cdbInfo.getHandle() == 0 || cdbInfo.getComponent() == null)
logger.log(Level.SEVERE, "Failed to activate CDB, invalid ComponentInfo returned: '" + cdbInfo + "'.");
else {
logger.log(Level.INFO, "CDB activated on container '" + containerInfo.getName() + "'.");
}
} catch (Throwable ex) {
logger.log(Level.SEVERE, "Failed to activate CDB on container '" + containerInfo.getName() + "'.", ex);
}
}
// used for fast lookups
Map<String, Integer> activationRequests = new HashMap<String, Integer>();
// order is important, preserve it
ArrayList<URI> activationRequestsList = new ArrayList<URI>();
// get CDB access daos
DAOProxy dao = getManagerDAOProxy();
DAOProxy componentsDAO = getComponentsDAOProxy();
//
if (dao != null && componentsDAO != null) {
try {
// query startup components
String[] startup = dao.get_string_seq("Startup");
final Integer managerHandle = new Integer(this.getHandle());
for (int i = 0; i < startup.length; i++) {
// TODO simulator test workaround
if (startup[i].length() == 0)
continue;
// read container field
String containerName = readStringCharacteristics(componentsDAO, startup[i] + "/Container");
if (containerName == null) {
logger.log(Level.WARNING, "Misconfigured CDB, there is no container of component '" + startup[i] + "' defined.");
continue;
}
// if container name matches, add activation request
if (containerInfo.getName().equals(containerName)) {
try {
URI curl = CURLHelper.createURI(startup[i]);
// check CURL
try {
checkCURL(curl);
} catch (RuntimeException e) {
// @todo Auto-generated catch block
e.printStackTrace();
}
activationRequestsList.add(curl);
activationRequests.put(startup[i], managerHandle);
} catch (URISyntaxException usi) {
logger.log(Level.WARNING, "Failed to create URI from component name '" + startup[i] + "'.", usi);
}
}
}
} catch (Throwable th) {
logger.log(Level.WARNING, "Failed to retrieve list of startup components.", th);
}
}
//
// autostart components (<component>.Autostart attribute)
//
final String TRUE_STRING = "true";
if (componentsDAO != null) {
try {
final Integer managerHandle = new Integer(this.getHandle());
// get names of all components
// TODO here to check if CDB is available
componentsDAO.get_field_data("");
/*String[] ids =*/
String[] ids = getComponentsList();
// test names
for (int i = 0; i < ids.length; i++) {
// read name
//readStringCharacteristics(componentsDAO, ids[i]+"/Name");
String name = ids[i];
if (name == null) {
logger.log(Level.WARNING, "Misconfigured CDB, there is no name of component '" + ids[i] + "' defined.");
continue;
}
// read autostart silently
String autostart = readStringCharacteristics(componentsDAO, ids[i] + "/Autostart", true);
if (autostart == null) {
logger.log(Level.WARNING, "Misconfigured CDB, there is no autostart attribute of component '" + ids[i] + "' defined.");
continue;
} else if (autostart.equalsIgnoreCase(TRUE_STRING) && !activationRequests.containsKey(name)) /* TODO to be removed */
{
// read container silently
String componentContainer = readStringCharacteristics(componentsDAO, ids[i] + "/Container", true);
if (componentContainer == null) {
logger.log(Level.WARNING, "Misconfigured CDB, there is no container attribute of component '" + ids[i] + "' defined.");
continue;
} else if (!containerInfo.getName().equals(componentContainer))
continue;
try {
URI curl = CURLHelper.createURI(name);
// check CURL, no non-local curls
try {
checkCURL(curl, false);
} catch (RuntimeException e) {
reportException(e);
}
activationRequestsList.add(curl);
activationRequests.put(name, managerHandle);
} catch (URISyntaxException usi) {
logger.log(Level.WARNING, "Failed to create URI from component name '" + name + "'.", usi);
}
}
}
} catch (Throwable ex) {
logger.log(Level.WARNING, "Failed to retrieve list of components.", ex);
}
}
// list of componentInfo to be cleaned up (cannot be immediately, due to lock)
ArrayList<ComponentInfo> cleanupList = new ArrayList<ComponentInfo>();
// check unavailable components
if (unavailableComponents.size() > 0) {
if (componentsDAO != null) {
try {
final Integer reactivateHandle = new Integer(0);
synchronized (unavailableComponents) {
String[] names = unavailableComponents.keySet().toArray(new String[unavailableComponents.size()]);
// reverse
for (int i = names.length - 1; i >= 0; i--) {
String name = names[i];
boolean reactivate = false;
// dynamic component check
ComponentInfo componentInfo = unavailableComponents.get(name);
if (componentInfo != null && componentInfo.isDynamic() && componentInfo.getDynamicContainerName() != null && componentInfo.getDynamicContainerName().equals(containerInfo.getName())) {
// reactivate dynamic component
reactivate = true;
} else {
// read container field
String containerName = readStringCharacteristics(componentsDAO, name + "/Container");
if (containerName == null) {
logger.log(Level.WARNING, "Misconfigured CDB, there is no container of component '" + name + "' defined.");
//continue;
} else // if container name matches, add (override) activation request
if (containerInfo.getName().equals(containerName)) {
reactivate = true;
}
}
if (reactivate) {
// clean up if in non-recovery mode
if (!recoverContainer) {
// and if not already in activation list (startup component)
if (!activationRequests.containsKey(name)) {
cleanupList.add(componentInfo);
continue;
}
}
// this Component needs reactivation
if (activationRequests.containsKey(name)) {
activationRequests.put(name, reactivateHandle);
} else // put to activation list
{
try {
activationRequestsList.add(CURLHelper.createURI(name));
activationRequests.put(name, reactivateHandle);
} catch (URISyntaxException usi) {
logger.log(Level.WARNING, "Failed to create URI from component name '" + name + "'.", usi);
}
}
}
}
}
} catch (Throwable ex) {
CoreException ce = new CoreException("Failed to obtain component data from the CDB.", ex);
reportException(ce);
}
}
}
if (cleanupList.size() > 0) {
Iterator<ComponentInfo> iter = cleanupList.iterator();
while (iter.hasNext()) {
ComponentInfo componentInfo = iter.next();
componentsLock.lock();
try {
// remove from its owners list ...
int[] owners = componentInfo.getClients().toArray();
for (int j = 0; j < owners.length; j++) removeComponentOwner(componentInfo.getHandle(), owners[j]);
// ... and deallocate
executeCommand(new ComponentCommandDeallocate(componentInfo.getHandle() & HANDLE_MASK, componentInfo.getHandle(), WhyUnloadedReason.REMOVED));
executeCommand(new UnavailableComponentCommandRemove(componentInfo.getName()));
// remove component from container component list
synchronized (containerInfo.getComponents()) {
if (containerInfo.getComponents().contains(componentInfo.getHandle()))
executeCommand(new ContainerInfoCommandComponentRemove(containerInfo.getHandle() & HANDLE_MASK, componentInfo.getHandle()));
}
} finally {
componentsLock.unlock();
}
// unbind from remote directory
//unbind(convertToHiearachical(componentInfo.getName()), "O");
}
}
logger.log(Level.INFO, "Container '" + containerInfo.getName() + "' startup statistics: " + activationRequestsList.size() + " components queued to be activated.");
// send message to the container
sendMessage(containerInfo.getContainer(), "Startup statistics: " + activationRequestsList.size() + " components queued to be activated.", MessageType.MSG_INFORMATION, ClientOperations.MSGID_AUTOLOAD_START);
// activate startup components
int activated = 0;
StatusHolder status = new StatusHolder();
Iterator<URI> iterator = activationRequestsList.iterator();
while (iterator.hasNext()) {
URI uri = iterator.next();
try {
String name = extractName(uri);
int requestor = activationRequests.get(name);
internalRequestComponent(requestor, uri, status);
if (status.getStatus() != ComponentStatus.COMPONENT_ACTIVATED)
logger.log(Level.WARNING, "Failed to activate autostart component '" + uri + "', reason: '" + status.getStatus() + "'.");
else
activated++;
} catch (Throwable ex) {
logger.log(Level.WARNING, "Failed to activate autostart component '" + uri + "'.", ex);
}
}
logger.log(Level.INFO, "Container '" + containerInfo.getName() + "' startup statistics: " + activated + " of " + activationRequestsList.size() + " components activated.");
// send message to the container
sendMessage(containerInfo.getContainer(), "Startup statistics: " + activated + " of " + activationRequestsList.size() + " components activated.", MessageType.MSG_INFORMATION, ClientOperations.MSGID_AUTOLOAD_END);
// notify about new container login
synchronized (containerLoggedInMonitor) {
containerLoggedInMonitor.notifyAll();
}
}
use of com.cosylab.acs.maci.manager.recovery.ContainerInfoCommandComponentRemove in project ACS by ACS-Community.
the class ManagerImpl method internalNoSyncDeactivateComponent.
/**
* Deactivate component, issue deactivate reeust to container (or other manager).
* @param componentInfo info about component to be deactivated.
*/
private void internalNoSyncDeactivateComponent(ComponentInfo componentInfo) throws Throwable {
// unbind from remote directory
//unbind(convertToHiearachical(componentInfo.getName()), "O");
int handle = componentInfo.getHandle() & HANDLE_MASK;
int owners = componentInfo.getClients().size();
try {
//
// get container/remote manager
//
String name = componentInfo.getName();
boolean isOtherDomainComponent = name.startsWith(CURL_URI_SCHEMA);
if (isOtherDomainComponent) {
Manager remoteManager = null;
// @todo MF do the login?
try {
String domainName = CURLHelper.createURI(name).getAuthority();
remoteManager = getManagerForDomain(domainName);
if (remoteManager == null)
throw new CoreException("Failed to obtain manager for domain '" + domainName + "'.");
} catch (Throwable th) {
logger.log(Level.WARNING, "Failed to obtain non-local manager required by component '" + name + "'.", th);
throw th;
}
// release component
try {
URI curlName = CURLHelper.createURI(name);
// @todo MF tmp (handle)
remoteManager.releaseComponent(INTERDOMAIN_MANAGER_HANDLE, curlName);
} catch (Throwable th) {
logger.log(Level.WARNING, "Failed to release component '" + componentInfo.getName() + "' on remote manager.'", th);
throw th;
}
} else {
//
// search for container by its name
//
Container container = null;
ContainerInfo containerInfo = null;
int containerHandle = componentInfo.getContainer();
// if containerHandle equals 0, we have unavailable or registered component
if (containerHandle != 0) {
containerInfo = getContainerInfo(containerHandle);
if (containerInfo != null) {
// remove component from container component list
synchronized (containerInfo.getComponents()) {
// !!! ACID
if (containerInfo.getComponents().contains(componentInfo.getHandle()))
executeCommand(new ContainerInfoCommandComponentRemove(containerInfo.getHandle() & HANDLE_MASK, componentInfo.getHandle()));
//containerInfo.getComponents().remove(componentInfo.getHandle());
}
// we allow this (since releasing components is part of container shutdown procedure)
//checkContainerState(containerInfo);
container = containerInfo.getContainer();
}
// required container is not logged in
if (container == null) {
// then simply do not do the deactivation
String containerName;
if (containerInfo != null)
containerName = containerInfo.getName();
else
containerName = HandleHelper.toString(componentInfo.getContainer());
logger.log(Level.WARNING, "Container '" + containerName + "' required by component '" + componentInfo.getName() + "' is not logged in.");
}
}
if (container != null) {
// log info
logger.log(Level.INFO, "Deactivating component '" + componentInfo.getName() + "' (" + HandleHelper.toString(componentInfo.getHandle()) + ") on container '" + containerInfo.getName() + "'.");
// destruct
try {
componentInfo.getComponent().destruct();
} catch (Throwable ex) {
RemoteException re = new RemoteException("Failed to destruct component '" + componentInfo.getName() + "', exception caught when invoking 'destruct()' method.", ex);
logger.log(Level.SEVERE, re.getMessage(), re);
throw ex;
}
long deactivationTime = 0;
// deactivate component in anycase
try {
container.deactivate_component(componentInfo.getHandle());
deactivationTime = System.currentTimeMillis();
} catch (AcsJException aex) {
logger.log(Level.SEVERE, aex.getMessage(), aex);
throw aex;
} catch (Throwable ex) {
RemoteException re = new RemoteException("Failed to deactivate component '" + componentInfo.getName() + "' (" + HandleHelper.toString(componentInfo.getHandle()) + ") on container '" + containerInfo.getName() + "'.", ex);
logger.log(Level.SEVERE, re.getMessage(), re);
throw ex;
}
// notify administrators about deactivation, but not if failed
if (deactivationTime != 0)
notifyComponentDeactivated(componentInfo.getHandle(), deactivationTime);
// shutdown container if required (and necessary)
conditionalShutdownContainer(containerInfo);
}
}
} finally {
if (owners == 0) {
// deallocate Component
componentsLock.lock();
try {
executeCommand(new ComponentCommandDeallocate(handle, componentInfo.getHandle(), WhyUnloadedReason.REMOVED));
//components.deallocate(handle);
} finally {
componentsLock.unlock();
}
}
}
// log info
logger.log(Level.INFO, "Component '" + componentInfo.getName() + "' (" + HandleHelper.toString(componentInfo.getHandle()) + ") deactivated.");
// release all subcomponents (just like client logoff)
// component should have already done this by itself, but take care of clean cleanup
// what about that: if subcomponent becomes unavailable, does component also becomes?!
// no, it is notified and it handles situation by its own way (e.g. changes component state).
// Just like it already handles activation (manager does not care for dependecy trees).
int[] subcomponents = null;
// no not hold the lock
synchronized (componentInfo.getComponents()) {
if (componentInfo.getComponents().size() > 0) {
IntArray toCleanupList = new IntArray();
IntArray comps = componentInfo.getComponents();
for (int i = 0; i < comps.size(); i++) if (components.isAllocated(comps.get(i) & HANDLE_MASK))
toCleanupList.add(comps.get(i));
if (toCleanupList.size() > 0)
subcomponents = toCleanupList.toArray();
}
//subcomponents = componentInfo.getComponents().toArray();
}
if (subcomponents != null && subcomponents.length > 0)
new ReleaseComponentTask(componentInfo.getHandle(), subcomponents).run();
// make unavailable (deactivation was forced)
if (owners > 0)
makeUnavailable(componentInfo);
}
use of com.cosylab.acs.maci.manager.recovery.ContainerInfoCommandComponentRemove in project ACS by ACS-Community.
the class ManagerImpl method containerInternalStateMerge.
/**
* Retrieve container's internal state and merge it with manager's.
* NOTE: this method should not be run in separate thread since states
* should be merged synchronously.
* Merge is split to two parts:
*
* <h2>Container -> Manager</h2>
*
* If container component handle is also allocated in manager state and components information match,
* then we have a perfect fit and no action is required. If they do not match, container is rejected.
* If container component handle is not allocated in the manager state and no component with
* same name is found in manager state, component information is transferred to the manager,
* owtherwise container is rejected.
* <p>
* NOTE: The second option allows components without owners to be activated.
* </p>
* <p>
* NOTE: Container is rejected due to its state inconsistency which will probably cause
* problems in the future. Container has to be restarted.<br/>
* (A more sophisticated algorithm could give manager "the power to shape up" container state.)
* </p>
* <p>
* NOTE: Container -> Manager has to work in the way transactions do, i.e. in case of rejection
* manager state should no be affected.
* </p>
*
* <h2>Manager -> Container</h2>
*
* If <code>recoverContainer</code> is <code>true</code>, all components known to the manager to
* be activated on this particular container and listed as activated by the container
* will be marked as unavailable to be reactivated later by
* <code>containerPostLoginActivation</code> method.
* If <code>recoverContainer</code> is <code>false</code>, all there information will be discared
* (components removed from container component list, deallocated, and removed from their owners list).
*
* @param containerInfo container info for which to perform merge, non-<code>null</code>.
* @param recoverContainer if <code>true</code> manager state will be 'transferred' to container.
*/
private void containerInternalStateMerge(ContainerInfo containerInfo, boolean recoverContainer) throws AcsJNoPermissionEx {
assert (containerInfo != null);
// firstly, query containers state
ComponentInfo[] infos = null;
try {
infos = containerInfo.getContainer().get_component_info(new int[0]);
} catch (Throwable ex) {
logger.log(Level.SEVERE, "Failed to query state of container '" + containerInfo.getName() + "'.", ex);
}
boolean requireTopologySort = false;
// copy elements
IntArray managerContainersComponents;
synchronized (containerInfo.getComponents()) {
managerContainersComponents = new IntArray(containerInfo.getComponents().toArray());
}
if (infos != null && infos.length > 0) {
componentsLock.lock();
try {
// phase 1: check for state consistency
for (int i = 0; i < infos.length; i++) {
// check if info is valid
if (infos[i].getHandle() == 0 || (infos[i].getHandle() & COMPONENT_MASK) != COMPONENT_MASK || infos[i].getName() == null || infos[i].getType() == null || infos[i].getCode() == null || infos[i].getComponent() == null || infos[i].getContainer() == 0 || infos[i].getInterfaces() == null) {
// bad info
// NO_PERMISSION
AcsJNoPermissionEx npe = new AcsJNoPermissionEx();
npe.setReason("Inconsistent container state - component information is not valid, rejecting container.");
npe.setID(containerInfo.getName());
npe.setProtectedResource(infos[i].getName());
throw npe;
}
int handle = infos[i].getHandle() & HANDLE_MASK;
if (components.isAllocated(handle)) {
// handle is allocated
// check if components information match
ComponentInfo componentInfo = (ComponentInfo) components.get(handle);
if (componentInfo == null || componentInfo.getHandle() != infos[i].getHandle() || !componentInfo.getName().equals(infos[i].getName()) || (componentInfo.getContainer() != 0 && componentInfo.getContainer() != infos[i].getContainer())) {
// information does not match, reject container
// NO_PERMISSION
AcsJNoPermissionEx npe = new AcsJNoPermissionEx();
npe.setReason("Inconsistent container state - components information do not match, rejecting container.");
npe.setID(containerInfo.getName());
if (componentInfo != null) {
npe.setProtectedResource(componentInfo.getName());
}
throw npe;
}
} else {
// handle is not allocated
// check if component with same name is already registered
int h = components.first();
while (h != 0) {
ComponentInfo componentInfo = (ComponentInfo) components.get(h);
if (componentInfo.getName().equals(infos[i].getName())) {
// yes it does, reject container
// NO_PERMISSION
AcsJNoPermissionEx npe = new AcsJNoPermissionEx();
npe.setReason("Inconsistent container state - component with name '" + componentInfo.getName() + "' already registered with different handle, rejecting container.");
npe.setID(containerInfo.getName());
npe.setProtectedResource(componentInfo.getName());
throw npe;
}
h = components.next(h);
}
}
}
// phase 2: do the transfer
for (int i = 0; i < infos.length; i++) {
int handle = infos[i].getHandle() & HANDLE_MASK;
if (components.isAllocated(handle)) {
// handle is allocated and info match
// just in case component is not persistent, update the reference
// is always non-null - checked already above
ComponentInfo componentInfo = (ComponentInfo) components.get(handle);
componentInfo.setComponent(infos[i].getComponent());
componentInfo.setContainer(infos[i].getContainer());
componentInfo.setContainerName(infos[i].getContainerName());
// remove if unavailable and notify
synchronized (unavailableComponents) {
// !!! ACID 3
executeCommand(new UnavailableComponentCommandRemove(componentInfo.getName()));
//unavailableComponents.remove(componentInfo.getName());
}
int[] clients = componentInfo.getClients().toArray();
notifyComponentAvailable(0, clients, new ComponentInfo[] { componentInfo });
} else {
// handle is not allocated
// transfer component
// create new ComponentInfo (we do not trust containers)
ComponentInfo info = new ComponentInfo(infos[i].getHandle(), infos[i].getName(), infos[i].getType(), infos[i].getCode(), infos[i].getComponent());
info.setContainer(infos[i].getContainer());
info.setContainerName(infos[i].getContainerName());
info.setInterfaces(infos[i].getInterfaces());
info.setAccessRights(0);
// if it has a CDB entry or if there is no CDB available
if (!hasCDBEntry(info)) {
info.setDynamic(true);
info.setDynamicContainerName(containerInfo.getName());
}
// !!! ACID 3
// allocate and store
executeCommand(new ComponentCommandAllocateHandle(handle));
//components.allocate(handle);
executeCommand(new ComponentCommandSet(handle, info));
//components.set(handle, info);
requireTopologySort = true;
}
// we handled this component
managerContainersComponents.remove(infos[i].getHandle());
// add to container component list
synchronized (containerInfo.getComponents()) {
// !!! ACID 3
if (!containerInfo.getComponents().contains(infos[i].getHandle()))
executeCommand(new ContainerInfoCommandComponentAdd(containerInfo.getHandle() & HANDLE_MASK, infos[i].getHandle()));
//containerInfo.getComponents().add(infos[i].getHandle());
}
}
} finally {
componentsLock.unlock();
}
}
// managerContainersComponents contains component handles not handled yet
for (int i = 0; i < managerContainersComponents.size(); i++) {
int componentHandle = managerContainersComponents.get(i);
// remove component handle from container component list
// will be added when actually activated
// !!! ACID 3
executeCommand(new ContainerInfoCommandComponentRemove(containerInfo.getHandle() & HANDLE_MASK, componentHandle));
//containerInfo.getComponents().remove(componentHandle);
// marked as unavailable to be reactivated later (or discarded)
componentsLock.lock();
try {
int handle = componentHandle & HANDLE_MASK;
if (components.isAllocated(handle)) {
ComponentInfo componentInfo = (ComponentInfo) components.get(handle);
// what if null (very not likely to happen, but possible)
if (componentInfo == null) {
// internal error, this should not happen
logger.log(Level.SEVERE, "Internal state is not consistent (no ComponentInfo).");
continue;
}
// notify component owners about Component deactivation
makeUnavailable(componentInfo);
if (!recoverContainer) {
// discard all Component information
// remove from its owners list ...
int[] owners = componentInfo.getClients().toArray();
for (int j = 0; j < owners.length; j++) removeComponentOwner(componentHandle, owners[j]);
// !!! ACID 3
// ... and deallocate
executeCommand(new ComponentCommandDeallocate(handle, componentInfo.getHandle(), WhyUnloadedReason.REMOVED));
//components.deallocate(handle);
requireTopologySort = true;
}
} else {
// internal error, this should not happen
logger.log(Level.SEVERE, "Internal state is not consistent.");
}
} finally {
componentsLock.unlock();
}
}
if (requireTopologySort)
topologySortManager.notifyTopologyChange(containerInfo.getHandle());
}
Aggregations