/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.component.update.internal; import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.communication.api.CommunicationService; import de.rcenvironment.core.communication.common.LogicalNodeId; import de.rcenvironment.core.component.update.api.DistributedPersistentComponentDescriptionUpdateService; import de.rcenvironment.core.component.update.api.PersistentComponentDescription; import de.rcenvironment.core.component.update.api.PersistentDescriptionFormatVersion; import de.rcenvironment.core.component.update.api.RemotablePersistentComponentDescriptionUpdateService; import de.rcenvironment.core.toolkitbridge.transitional.ConcurrencyUtils; import de.rcenvironment.core.utils.common.StringUtils; import de.rcenvironment.core.utils.common.rpc.RemoteOperationException; import de.rcenvironment.toolkit.modules.concurrency.api.AsyncExceptionListener; import de.rcenvironment.toolkit.modules.concurrency.api.CallablesGroup; import de.rcenvironment.toolkit.modules.concurrency.api.TaskDescription; /** * Implementation of {@link DistributedPersistentComponentDescriptionUpdateService}. * * @author Doreen Seider */ public class DistributedPersistentComponentDescriptionUpdateServiceImpl implements DistributedPersistentComponentDescriptionUpdateService { private static final Log LOGGER = LogFactory.getLog(DistributedPersistentComponentDescriptionUpdateServiceImpl.class); private CommunicationService communicationService; @Override public int getFormatVersionsAffectedByUpdate(List<PersistentComponentDescription> descriptions, final boolean silent) { int versionsToUpdate = PersistentDescriptionFormatVersion.NONE; CallablesGroup<Integer> callablesGroup = ConcurrencyUtils.getFactory().createCallablesGroup(Integer.class); final Map<LogicalNodeId, List<PersistentComponentDescription>> sortedDescriptionsMap = Collections.unmodifiableMap(sortPersistentComponentDescriptions(descriptions)); for (LogicalNodeId node : sortedDescriptionsMap.keySet()) { final LogicalNodeId node2 = node; callablesGroup.add(new Callable<Integer>() { @Override @TaskDescription("Distributed persistent component update check: getFormatVersionsAffectedByUpdate()") public Integer call() throws Exception { try { RemotablePersistentComponentDescriptionUpdateService udpateService = communicationService .getRemotableService(RemotablePersistentComponentDescriptionUpdateService.class, node2); return udpateService.getFormatVersionsAffectedByUpdate(sortedDescriptionsMap.get(node2), silent); } catch (RemoteOperationException | RuntimeException e) { LOGGER.warn(StringUtils.format("Failed to check for persistent component updates for node: %s; cause: %s", node2, e.toString())); return null; } } }); List<Integer> results = callablesGroup.executeParallel(new AsyncExceptionListener() { @Override public void onAsyncException(Exception e) { LOGGER.warn("Exception during asynchrous execution", e); } }); // merge results for (Integer singleResult : results) { if (singleResult != null) { versionsToUpdate = versionsToUpdate | singleResult; } } } return versionsToUpdate; } @Override public List<PersistentComponentDescription> performComponentDescriptionUpdates(final int formatVersion, List<PersistentComponentDescription> descriptions, final boolean silent) throws IOException { List<PersistentComponentDescription> allUpdatedDescriptions = new ArrayList<PersistentComponentDescription>(); final Map<LogicalNodeId, List<PersistentComponentDescription>> sortedDescriptionsMap = Collections.unmodifiableMap(sortPersistentComponentDescriptions(descriptions)); final List<PersistentComponentDescription> unModdescriptions = Collections.unmodifiableList(descriptions); CallablesGroup<List> callablesGroup = ConcurrencyUtils.getFactory().createCallablesGroup(List.class); for (LogicalNodeId node : sortedDescriptionsMap.keySet()) { final LogicalNodeId node2 = node; callablesGroup.add(new Callable<List>() { @Override @TaskDescription("Distributed persistent component update: performComponentDescriptionUpdates()") public List call() throws Exception { RemotablePersistentComponentDescriptionUpdateService updateService = communicationService .getRemotableService(RemotablePersistentComponentDescriptionUpdateService.class, node2); if ((updateService.getFormatVersionsAffectedByUpdate(unModdescriptions, silent) & formatVersion) == formatVersion) { try { return updateService .performComponentDescriptionUpdates(formatVersion, sortedDescriptionsMap.get(node2), silent); } catch (UndeclaredThrowableException e) { LOGGER.warn("Failed to perform persistent component updates for node: " + node2, e); return null; } } else { return sortedDescriptionsMap.get(node2); } } }); } List<List> results = callablesGroup.executeParallel(new AsyncExceptionListener() { @Override public void onAsyncException(Exception e) { LOGGER.warn("Exception during asynchrous execution", e); } }); // merge results for (List singleResult : results) { if (singleResult != null) { allUpdatedDescriptions.addAll(singleResult); } } return allUpdatedDescriptions; } protected void bindCommunicationService(CommunicationService newCommunicationService) { this.communicationService = newCommunicationService; } private Map<LogicalNodeId, List<PersistentComponentDescription>> sortPersistentComponentDescriptions( List<PersistentComponentDescription> descriptions) { Map<LogicalNodeId, List<PersistentComponentDescription>> sortedDescriptions = new HashMap<LogicalNodeId, List<PersistentComponentDescription>>(); for (PersistentComponentDescription description : descriptions) { if (!sortedDescriptions.containsKey(description.getComponentNodeIdentifier())) { sortedDescriptions.put(description.getComponentNodeIdentifier(), new ArrayList<PersistentComponentDescription>()); } sortedDescriptions.get(description.getComponentNodeIdentifier()).add(description); } return sortedDescriptions; } }