use of com.cosylab.acs.maci.manager.recovery.ComponentCommandSet in project ACS by ACS-Community.
the class ManagerImpl method internalNoSyncRequestComponentPhase2.
private ComponentInfo internalNoSyncRequestComponentPhase2(int requestor, String name, String type, String code, String containerName, int keepAliveTime, StatusHolder status, AcsJCannotGetComponentEx bcex, boolean isOtherDomainComponent, boolean isDynamicComponent, int h, boolean reactivate, ComponentInfo componentInfo, Container container, ContainerInfo containerInfo, long executionId, long activationTime, boolean timeoutError) throws AcsJCannotGetComponentEx {
// remove component from client component list, will be added later (first lots of checks has to be done)
if ((requestor & TYPE_MASK) == COMPONENT_MASK) {
removeComponentOwner(h | COMPONENT_MASK, requestor);
}
// remove from pending activation list
synchronized (pendingActivations) {
pendingActivations.remove(name);
}
// failed to activate
if (componentInfo == null || componentInfo.getHandle() == 0 || componentInfo.getComponent() == null) {
if (bcex == null)
logger.log(Level.SEVERE, "Failed to activate component '" + name + "' (" + HandleHelper.toString(h | COMPONENT_MASK) + ").");
else
bcex.setReason("Failed to activate component '" + name + "' (" + HandleHelper.toString(h | COMPONENT_MASK) + ").");
componentsLock.lock();
try {
// !!! ACID 3
if (!reactivate)
executeCommand(new ComponentCommandDeallocate(h, h | COMPONENT_MASK, timeoutError ? WhyUnloadedReason.TIMEOUT : WhyUnloadedReason.REMOVED, true));
//components.deallocate(h, true);
} finally {
componentsLock.unlock();
}
status.setStatus(ComponentStatus.COMPONENT_NOT_ACTIVATED);
if (bcex == null)
return null;
else
throw bcex;
}
// log info
logger.log(Level.INFO, "Component '" + name + "' (" + HandleHelper.toString(h | COMPONENT_MASK) + ") activated successfully.");
//
if (!isOtherDomainComponent && !componentInfo.getComponent().doesImplement(type)) {
// just output SEVERE message
logger.log(Level.SEVERE, "Activated component '" + name + "' does not implement specified type '" + type + "'.");
}
// component info (to get type and code, container - prefix name)
if (isOtherDomainComponent) {
// @todo MF tmp (for testing)
componentInfo.setHandle(h | COMPONENT_MASK);
componentInfo.setClients(new IntArray());
componentInfo.setComponents(new IntArray(0));
componentInfo.setContainer(0);
// set variables
type = componentInfo.getType();
code = componentInfo.getCode();
}
int[] clients;
componentsLock.lock();
try {
//
if (componentInfo.getHandle() != (h | COMPONENT_MASK)) {
// container returned different handle
// (it seems it has already activated this Component)
// check if we can accept it
int componentHandle = componentInfo.getHandle() & HANDLE_MASK;
if (components.isAllocated(componentHandle)) {
// cancel preallocation
if (!reactivate)
executeCommand(new ComponentCommandDeallocate(h, componentInfo.getHandle(), WhyUnloadedReason.REMOVED, true));
//components.deallocate(h, true);
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Container '" + containerName + "' returned another '" + name + "' component handle than given, failed to fix handle since returned handle is already allocated.");
// log this anyway, since it's an error of a global nature
logger.log(Level.SEVERE, "Container '" + containerName + "' returned another '" + name + "' component handle than given, failed to fix handle since returned handle is already allocated.", bcex);
// component is activated, but cannot be managed by the Manager
status.setStatus(ComponentStatus.COMPONENT_ACTIVATED);
throw bcex;
} else {
// handle is free, relocate handle
ComponentInfo existingData = null;
// deallocate old
if (!reactivate)
executeCommand(new ComponentCommandDeallocate(h, componentInfo.getHandle(), WhyUnloadedReason.REPLACED, true));
else //components.deallocate(h, true);
{
// !!! ACID 3
existingData = (ComponentInfo) components.get(h);
executeCommand(new ComponentCommandDeallocate(h, componentInfo.getHandle(), WhyUnloadedReason.REPLACED));
//components.deallocate(h);
}
// !!! ACID 3
// preallocate new
Integer objHandle = (Integer) executeCommand(new ComponentCommandAllocateHandle(componentHandle, true));
//h = components.allocate(componentHandle, true);
if (objHandle == null || (h = objHandle.intValue()) == 0) {
// failed to allocate new
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Container '" + containerName + "' returned another '" + name + "' component handle than given, failed to fix handle due to handle relocation failure.");
// log this anyway, since it's an error of a global nature
logger.log(Level.SEVERE, "Container '" + containerName + "' returned another '" + name + "' component handle than given, failed to fix handle due to handle relocation failure.", bcex);
// Component is activated, but cannot be managed by the Manager
status.setStatus(ComponentStatus.COMPONENT_ACTIVATED);
throw bcex;
} else // !!! ACID 3
if (existingData != null)
executeCommand(new ComponentCommandSet(h, existingData));
//components.set(h, existingData);
logger.log(Level.WARNING, "Container '" + containerName + "' returned another '" + name + "' component handle than given, handle fixed.");
}
}
//
// pre-store data
//
ComponentInfo existingData = (ComponentInfo) components.get(h);
// create a new ComponentInfo - do not trust containers
ComponentInfo data = new ComponentInfo(componentInfo.getHandle(), name, type, code, componentInfo.getComponent());
if (existingData != null) {
data.setClients(existingData.getClients());
data.setComponents(existingData.getComponents());
}
if (requestor != 0)
if (// hierarchical components need this check
!data.getClients().contains(requestor))
data.getClients().add(requestor);
if (keepAliveTime <= RELEASE_NEVER)
if (// make component immortal
!data.getClients().contains(this.getHandle()))
data.getClients().add(this.getHandle());
// remember keep alive time
data.setKeepAliveTime(keepAliveTime);
if (isOtherDomainComponent) {
data.setContainer(0);
data.setContainerName(componentInfo.getContainerName());
} else {
data.setContainer(containerInfo.getHandle());
data.setContainerName(containerInfo.getName());
}
data.setAccessRights(0);
data.setInterfaces(componentInfo.getInterfaces());
// mark as dynamic component and store its container
if (isDynamicComponent) {
data.setDynamic(true);
data.setDynamicContainerName(containerName);
}
// !!! ACID
executeCommand(new ComponentCommandSet(h, data));
// acknowledge allocation
if (!reactivate)
// !!! ACID 2
executeCommand(new ComponentCommandAckAlloc(h));
//components.ackAllocation(h);
componentInfo = data;
clients = componentInfo.getClients().toArray();
} finally {
componentsLock.unlock();
}
if (!isOtherDomainComponent) {
// add component to client component list to allow dependency checks
if ((requestor & TYPE_MASK) == COMPONENT_MASK)
addComponentOwner(componentInfo.getHandle(), requestor);
//
// call construct
//
boolean constructed = false;
try {
componentInfo.getComponent().construct();
constructed = true;
} catch (Throwable ex) {
bcex = new AcsJCannotGetComponentEx(ex);
bcex.setReason("Failed to construct component '" + name + "', exception caught when invoking 'construct()' method.");
}
// remove component from client component list, will be added later
if ((requestor & TYPE_MASK) == COMPONENT_MASK)
removeComponentOwner(componentInfo.getHandle(), requestor);
if (!constructed) {
// release Component
componentsLock.lock();
try {
// !!! ACID 3
if (!reactivate)
executeCommand(new ComponentCommandDeallocate(h, componentInfo.getHandle(), WhyUnloadedReason.REMOVED));
// deactivate
try {
container.deactivate_component(componentInfo.getHandle());
} catch (Exception ex) {
bcex = new AcsJCannotGetComponentEx(ex);
bcex.setReason("Failed to deactivate component '" + name + "' on container '" + containerName + "'.");
}
status.setStatus(ComponentStatus.COMPONENT_NOT_ACTIVATED);
throw bcex;
} finally {
componentsLock.unlock();
}
}
}
// add component to client component list
if (requestor != this.getHandle() && requestor != 0)
addComponentOwner(componentInfo.getHandle(), requestor);
// add component to container component list
if (!isOtherDomainComponent)
synchronized (containerInfo.getComponents()) {
if (!containerInfo.getComponents().contains(componentInfo.getHandle()))
executeCommand(new ContainerInfoCommandComponentAdd(containerInfo.getHandle() & HANDLE_MASK, componentInfo.getHandle()));
//containerInfo.getComponents().add(componentInfo.getHandle());
}
// remove component from unavailable list
if (reactivate) {
synchronized (unavailableComponents) {
executeCommand(new UnavailableComponentCommandRemove(name));
//unavailableComponents.remove(name);
}
}
//
if (!isOtherDomainComponent)
notifyComponentActivated(componentInfo, activationTime, executionId);
//
if (reactivate) {
notifyComponentAvailable(requestor, clients, new ComponentInfo[] { componentInfo });
}
//
// notify administrators about the activation
//
notifyComponentRequested(new int[] { requestor }, new int[] { componentInfo.getHandle() }, activationTime);
if (reactivate)
logger.log(Level.FINE, "Component '" + name + "' (" + HandleHelper.toString(componentInfo.getHandle()) + ") reactivated.");
else
logger.log(Level.FINE, "Component '" + name + "' (" + HandleHelper.toString(componentInfo.getHandle()) + ") activated.");
// notify about the change (only this-domain container which activated the component)...
if (containerInfo != null)
topologySortManager.notifyTopologyChange(containerInfo.getHandle());
status.setStatus(ComponentStatus.COMPONENT_ACTIVATED);
return componentInfo;
}
use of com.cosylab.acs.maci.manager.recovery.ComponentCommandSet in project ACS by ACS-Community.
the class ManagerImpl method internalNoSyncRequestComponent.
/**
* Internal method for requesting components (non sync).
* @param requestor requestor of the component.
* @param name name of component to be requested, non-<code>null</code>.
* @param type type of component to be requested; if <code>null</code> CDB will be queried.
* @param code code of component to be requested; if <code>null</code> CDB will be queried.
* @param containerName container name of component to be requested; if <code>null</code> CDB will be queried.
* @param status returned completion status of the request.
* @param activate <code>true</code> if component has to be activated
* @return componentInfo <code>ComponentInfo</code> of requested component.
*/
private ComponentInfo internalNoSyncRequestComponent(int requestor, String name, String type, String code, String containerName, int keepAliveTime, StatusHolder status, boolean activate) throws AcsJCannotGetComponentEx, AcsJComponentSpecIncompatibleWithActiveComponentEx {
AcsJCannotGetComponentEx bcex = null;
if (name == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Cannot activate component with NULL name.");
throw bcex;
}
if (status == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Component " + name + " has NULL status.");
throw bcex;
}
boolean isOtherDomainComponent = name.startsWith(CURL_URI_SCHEMA);
boolean isDynamicComponent = isOtherDomainComponent ? false : (type != null || code != null || containerName != null);
//
// check if component is already activated
//
int h;
// if true, component with handle h will be reactivated
boolean reactivate = false;
ComponentInfo componentInfo = null;
componentsLock.lock();
try {
h = components.first();
while (h != 0) {
componentInfo = (ComponentInfo) components.get(h);
if (componentInfo.getName().equals(name)) {
// check if component is unavailable
synchronized (unavailableComponents) {
if (unavailableComponents.containsKey(name)) {
// try to reactivate, possible component reallocation
reactivate = true;
}
}
// check for consistency
ContainerInfo containerInfo = getContainerInfo(componentInfo.getContainer());
if ((type != null && !componentInfo.getType().equals(type)) || (code != null && componentInfo.getCode() != null && !componentInfo.getCode().equals(code)) || (!reactivate && containerInfo != null && containerName != null && !containerInfo.getName().equals(containerName))) {
AcsJComponentSpecIncompatibleWithActiveComponentEx ciwace = new AcsJComponentSpecIncompatibleWithActiveComponentEx();
ciwace.setCURL(componentInfo.getName());
ciwace.setComponentType(componentInfo.getType());
ciwace.setComponentCode(componentInfo.getCode() != null ? componentInfo.getCode() : "<unknown>");
ciwace.setContainerName(containerInfo != null ? containerInfo.getName() : "<none>");
throw ciwace;
}
if (activate) {
// bail out and reactivate
if (reactivate)
break;
// add client/component as an owner (if requestor is not 'reactivation')
if (requestor != 0) {
// !!! ACID
if (!componentInfo.getClients().contains(requestor))
executeCommand(new ComponentCommandClientAdd(componentInfo.getHandle() & HANDLE_MASK, requestor));
//componentInfo.getClients().add(requestor);
}
// add component to client component list (if requestor is not manager or 'reactivation')
if (requestor != this.getHandle() && requestor != 0)
addComponentOwner(componentInfo.getHandle(), requestor);
// inform administrators about component request
notifyComponentRequested(new int[] { requestor }, new int[] { componentInfo.getHandle() }, System.currentTimeMillis());
// on complete system shutdown sort will be done anyway
if ((requestor & TYPE_MASK) == COMPONENT_MASK) {
ComponentInfo requestorComponentInfo = getComponentInfo(requestor);
if (requestorComponentInfo != null && requestorComponentInfo.getContainerName() != null && requestorComponentInfo.getContainerName().equals(componentInfo.getContainerName()))
topologySortManager.notifyTopologyChange(componentInfo.getContainer());
}
// return info
status.setStatus(ComponentStatus.COMPONENT_ACTIVATED);
return componentInfo;
} else {
if (reactivate)
status.setStatus(ComponentStatus.COMPONENT_NOT_ACTIVATED);
else
status.setStatus(ComponentStatus.COMPONENT_ACTIVATED);
return componentInfo;
}
}
h = components.next(h);
}
} finally {
componentsLock.unlock();
}
// and do not touch CDB
if (reactivate && componentInfo.isDynamic()) {
if (componentInfo.getType() == null || componentInfo.getCode() == null || componentInfo.getDynamicContainerName() == null) {
// failed
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Failed to reactivate dynamic component '" + componentInfo + "'.");
status.setStatus(ComponentStatus.COMPONENT_DOES_NO_EXIST);
throw bcex;
} else {
// reread info
type = componentInfo.getType();
code = componentInfo.getCode();
containerName = componentInfo.getDynamicContainerName();
keepAliveTime = componentInfo.getKeepAliveTime();
}
} else // is CDB lookup needed
if (!isOtherDomainComponent && (type == null || code == null || containerName == null)) {
//
// read component info from CDB / remote directory lookup
//
DAOProxy dao = getComponentsDAOProxy();
if (dao == null || readStringCharacteristics(dao, name, true) == null) {
// component with this name does not exists,
// make a remote directory lookup
Object ref = lookup(name, null);
if (ref != null) {
// found
status.setStatus(ComponentStatus.COMPONENT_ACTIVATED);
return new ComponentInfo(0, name, null, null, new ServiceComponent(ref));
} else {
// not found
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Component " + name + " not found in CDB.");
status.setStatus(ComponentStatus.COMPONENT_DOES_NO_EXIST);
throw bcex;
}
}
if (code == null) {
code = readStringCharacteristics(dao, name + "/Code");
if (code == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Misconfigured CDB, there is no code of component '" + name + "' defined.");
status.setStatus(ComponentStatus.COMPONENT_DOES_NO_EXIST);
throw bcex;
}
}
if (type == null) {
type = readStringCharacteristics(dao, name + "/Type");
if (type == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Misconfigured CDB, there is no type of component '" + name + "' defined.");
status.setStatus(ComponentStatus.COMPONENT_DOES_NO_EXIST);
throw bcex;
}
}
if (containerName == null) {
containerName = readStringCharacteristics(dao, name + "/Container");
if (containerName == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Misconfigured CDB, there is no container of component '" + name + "' defined.");
status.setStatus(ComponentStatus.COMPONENT_DOES_NO_EXIST);
throw bcex;
}
}
if (keepAliveTime == RELEASE_TIME_UNDEFINED) {
// defaults to 0 == RELEASE_IMMEDIATELY
keepAliveTime = readLongCharacteristics(dao, name + "/KeepAliveTime", RELEASE_IMMEDIATELY, true);
}
}
// we have keepAlive missing, try to get it
if (keepAliveTime == RELEASE_TIME_UNDEFINED) {
DAOProxy dao = getComponentsDAOProxy();
if (dao != null) {
// defaults to 0 == RELEASE_IMMEDIATELY
keepAliveTime = readLongCharacteristics(dao, name + "/KeepAliveTime", RELEASE_IMMEDIATELY, true);
} else {
// this is a case where all data for dynamic component is specified and there is not entry in CDB
keepAliveTime = RELEASE_IMMEDIATELY;
}
}
// read impl. language.
DAOProxy dao = getComponentsDAOProxy();
String componentImplLang = null;
if (dao != null) {
// silent read
componentImplLang = readStringCharacteristics(dao, name + "/ImplLang", true);
}
// if requestor did not request activation we are finished
if (!activate) {
status.setStatus(ComponentStatus.COMPONENT_NOT_ACTIVATED);
return null;
}
/****************** component activation ******************/
//
// get container/remote manager
//
Container container = null;
ContainerInfo containerInfo = null;
Manager remoteManager = null;
if (isOtherDomainComponent) {
// @todo MF do the login?
try {
String domainName = CURLHelper.createURI(name).getAuthority();
remoteManager = getManagerForDomain(domainName);
if (remoteManager == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Failed to obtain manager for domain '" + domainName + "'.");
throw bcex;
}
} catch (Throwable th) {
bcex = new AcsJCannotGetComponentEx(th);
bcex.setReason("Failed to obtain non-local manager required by component '" + name + "'.'");
status.setStatus(ComponentStatus.COMPONENT_NOT_ACTIVATED);
throw bcex;
}
} else {
// search for container by its name
containerInfo = getContainerInfo(containerName);
// try to start-up container
if (containerInfo == null)
containerInfo = startUpContainer(containerName);
// check state and get container
if (containerInfo != null) {
checkContainerShutdownState(containerInfo);
container = containerInfo.getContainer();
}
// required container is not logged in
if (container == null) {
bcex = new AcsJCannotGetComponentEx();
bcex.setReason("Container '" + containerName + "' required by component '" + name + "' is not logged in.");
status.setStatus(ComponentStatus.COMPONENT_NOT_ACTIVATED);
throw bcex;
}
}
// check container vs component ImplLang
ImplLang containerImplLang = containerInfo.getImplLang();
if (containerImplLang != null && containerImplLang != ImplLang.not_specified) {
if (componentImplLang != null && ImplLang.fromString(componentImplLang) != containerImplLang) {
AcsJCannotGetComponentEx af = new AcsJCannotGetComponentEx();
af.setReason("Component and container implementation language do not match (" + componentImplLang + " != " + containerImplLang.name() + ")");
throw af;
}
}
//
// get handle
//
// obtain handle
componentsLock.lock();
try {
// only preallocate (if necessary)
if (!reactivate) {
// !!! ACID 2
Integer objHandle = (Integer) executeCommand(new ComponentCommandPreallocate());
h = (objHandle == null) ? 0 : objHandle.intValue();
//h = components.preallocate();
}
// failed to obtain handle
if (h == 0) {
AcsJCannotGetComponentEx af = new AcsJCannotGetComponentEx();
af.setReason("Preallocation of new handle failed, too many registered components.");
throw af;
}
// create temporary ComponentInfo - to allow hierarchical components
if (!reactivate) {
ComponentInfo data = new ComponentInfo(h | COMPONENT_MASK, name, type, code, null);
data.setKeepAliveTime(keepAliveTime);
// !!! ACID
executeCommand(new ComponentCommandSet(h, data));
// add to pending activation list
synchronized (pendingActivations) {
pendingActivations.put(name, data);
}
// add component to client component list to allow dependency checks
if ((requestor & TYPE_MASK) == COMPONENT_MASK)
addComponentOwner(data.getHandle(), requestor);
}
} finally {
componentsLock.unlock();
}
//
// invoke get_component
//
componentInfo = null;
long executionId = 0;
long activationTime = 0;
boolean timeoutError = false;
if (isOtherDomainComponent) {
try {
URI curlName = CURLHelper.createURI(name);
StatusHolder statusHolder = new StatusHolder();
// @todo MF tmp (handle)
remoteManager.getComponent(INTERDOMAIN_MANAGER_HANDLE, curlName, true, statusHolder);
activationTime = System.currentTimeMillis();
if (statusHolder.getStatus() == ComponentStatus.COMPONENT_ACTIVATED) {
// local name to be used
String localName = curlName.getPath();
if (localName.charAt(0) == '/')
localName = localName.substring(1);
/// @TODO MF tmp (handle)
ComponentInfo[] infos = remoteManager.getComponentInfo(INTERDOMAIN_MANAGER_HANDLE, new int[0], localName, "*", true);
if (infos != null && infos.length == 1) {
componentInfo = infos[0];
// fix container name
componentInfo.setContainerName(CURL_URI_SCHEMA + curlName.getAuthority() + "/" + componentInfo.getContainerName());
}
//else
// throw new RemoteException("Failed to obtain component info for '"+name+"' from remote manager.");
}
//else
// throw new RemoteException("Failed to obtain component '"+name+"' from remote manager, status: " + statusHolder.getStatus() + ".");
} catch (Throwable ex) {
bcex = new AcsJCannotGetComponentEx(ex);
bcex.setReason("Failed to obtain component '" + name + "' from remote manager.");
timeoutError = (ex instanceof TimeoutRemoteException);
}
} else {
//
// invoke get_component on container
//
// log info
String handleReadable = HandleHelper.toString(h | COMPONENT_MASK);
logger.log(Level.INFO, "Activating component '" + name + "' (" + handleReadable + ") on container '" + containerInfo.getName() + "'.");
boolean callSyncActivate = System.getProperties().containsKey(NAME_SYNC_ACTIVATE);
if (callSyncActivate) {
// sync
try {
executionId = generateExecutionId();
activationTime = System.currentTimeMillis();
componentInfo = container.activate_component(h | COMPONENT_MASK, executionId, name, code, type);
} catch (Throwable ex) {
bcex = new AcsJCannotGetComponentEx(ex);
bcex.setReason("Failed to activate component '" + name + "' on container '" + containerName + "'.");
timeoutError = (ex instanceof TimeoutRemoteException);
}
} else {
// async
try {
executionId = generateExecutionId();
activationTime = System.currentTimeMillis();
ComponentInfoCompletionCallbackImpl callback = new ComponentInfoCompletionCallbackImpl(requestor, name, type, code, containerName, keepAliveTime, status, isOtherDomainComponent, isDynamicComponent, h, reactivate, container, containerInfo, executionId, activationTime);
addPendingContainerAsyncRequest(containerName, callback);
try {
container.activate_component_async(h | COMPONENT_MASK, executionId, name, code, type, callback);
} catch (Throwable t) {
// failed call, remove async request from the list
removePendingContainerAsyncRequest(containerName, callback);
throw t;
}
logger.log(AcsLogLevel.DELOUSE, "Asynchronous activation of component '" + name + "' (" + handleReadable + ") is running on container '" + containerInfo.getName() + "'.");
ComponentInfo ret;
try {
ret = callback.waitUntilActivated(getLockTimeout());
} catch (Throwable t) {
// failed call (most likely timeout), remove async request from the list
removePendingContainerAsyncRequest(containerName, callback);
throw t;
}
logger.log(AcsLogLevel.DELOUSE, "Asynchronous activation of component '" + name + "' (" + handleReadable + ") has finished on container '" + containerInfo.getName() + "'.");
return ret;
} catch (Throwable ex) {
bcex = new AcsJCannotGetComponentEx(ex);
bcex.setReason("Failed to activate component '" + name + "' on container '" + containerName + "'.");
throw bcex;
}
}
}
// call this immediately if bcex != null or sync call
return internalNoSyncRequestComponentPhase2(requestor, name, type, code, containerName, keepAliveTime, status, bcex, isOtherDomainComponent, isDynamicComponent, h, reactivate, componentInfo, container, containerInfo, executionId, activationTime, timeoutError);
}
use of com.cosylab.acs.maci.manager.recovery.ComponentCommandSet in project ACS by ACS-Community.
the class ManagerImpl method registerComponent.
/**
* @see com.cosylab.acs.maci.Manager#registerComponent(int, URI, String, Component)
*/
public int registerComponent(int id, URI curl, String type, Component component) throws AcsJNoPermissionEx, AcsJBadParameterEx {
// check for null
if (curl == null) {
AcsJBadParameterEx af = new AcsJBadParameterEx();
af.setParameter("curl");
af.setParameterValue("null");
throw af;
}
if (type == null) {
AcsJBadParameterEx af = new AcsJBadParameterEx();
af.setParameter("type");
af.setParameterValue("null");
throw af;
}
if (component == null) {
AcsJBadParameterEx af = new AcsJBadParameterEx();
af.setParameter("component");
af.setParameterValue("null");
throw af;
}
// Just rethrow the exception
try {
checkCURL(curl, false);
} catch (AcsJBadParameterEx e) {
throw e;
}
// check handle and REGISTER_COMPONENT permissions
securityCheck(id, AccessRights.REGISTER_COMPONENT);
/****************************************************************/
// extract name
String name = extractName(curl);
int h = 0;
componentsLock.lock();
try {
// check if Component is already registred
// if it is, return existing info
h = components.first();
while (h != 0) {
ComponentInfo registeredComponentInfo = (ComponentInfo) components.get(h);
if (registeredComponentInfo.getName().equals(name)) {
if (registeredComponentInfo.getType().equals(type)) {
// it is already activated, add manager as an owner and return handle
if (!registeredComponentInfo.getClients().contains(this.getHandle())) {
// ACID - !!!
executeCommand(new ComponentCommandClientAdd(registeredComponentInfo.getHandle() & HANDLE_MASK, this.getHandle()));
//registredComponentInfo.getClients().add(this.getHandle());
}
return registeredComponentInfo.getHandle();
} else {
AcsJNoPermissionEx npe = new AcsJNoPermissionEx();
npe.setReason("Component with name '" + name + "' but different type already registered.");
npe.setID(HandleHelper.toString(id));
npe.setProtectedResource(name);
throw npe;
}
}
h = components.next(h);
}
// allocate new handle
// !!! ACID 2
Integer objHandle = (Integer) executeCommand(new ComponentCommandAllocate());
int handle;
//int handle = components.allocate();
if (objHandle == null || (handle = objHandle.intValue()) == 0) {
NoResourcesException af = new NoResourcesException("Generation of new handle failed, too many components registred.");
throw af;
}
// generate external handle
h = handle | COMPONENT_MASK;
// add generated key
h |= (random.nextInt(0x100)) << 16;
// create new component info
ComponentInfo componentInfo = new ComponentInfo(h, name, type, null, component);
// no container
componentInfo.setContainer(0);
componentInfo.setContainerName(null);
// components can register other components
componentInfo.setAccessRights(AccessRights.REGISTER_COMPONENT);
// set Manager as client of the Component (to keep it immortal)
componentInfo.getClients().add(this.getHandle());
// set interfaces
// NOTE: this could block since it is a remote call
componentInfo.setInterfaces(component.implementedInterfaces());
// !!! ACID - register AddComponentCommand
executeCommand(new ComponentCommandSet(handle, componentInfo));
// store info
//components.set(handle, componentInfo);
} finally {
componentsLock.unlock();
}
// bind to remote directory
// NOTE: this could block since it is a remote call
//bind(convertToHiearachical(name), "O", component);
logger.log(Level.INFO, "Component '" + name + "' registered.");
return h;
}
use of com.cosylab.acs.maci.manager.recovery.ComponentCommandSet 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