/* * This file is part of LCMC written by Rasto Levrinc. * * Copyright (C) 2016, Rastislav Levrinc. * * The LCMC is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your option) * any later version. * * The LCMC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LCMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ package lcmc.crm.ui.resource.update; import com.google.common.base.Optional; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lcmc.cluster.ui.ClusterBrowser; import lcmc.common.domain.Application; import lcmc.crm.domain.CrmXml; import lcmc.crm.domain.RscSetConnectionData; import lcmc.crm.ui.CrmGraph; import lcmc.crm.ui.resource.ConstraintPHInfo; import lcmc.crm.ui.resource.PcmkRscSetsInfo; import lcmc.crm.ui.resource.ServiceInfo; import lombok.Getter; import javax.inject.Provider; import java.util.Collection; import java.util.List; import java.util.Map; public class RscSetUpdater { private final Application.RunMode runMode; private final ClusterBrowser browser; private final Provider<ConstraintPHInfo> constraintPHInfoProvider; private final Provider<PcmkRscSetsInfo> pcmkRscSetsInfoProvider; private final CrmGraph crmGraph; @Getter private List<ServiceInfo> serviceIsPresent = Lists.newArrayList(); private Map<RscSetConnectionData, ConstraintPHInfo> oldResourceSetToPlaceholder = Maps.newLinkedHashMap(); private List<ConstraintPHInfo> preNewCphis = Lists.newArrayList(); private Collection<ConstraintPHInfo> newCphis = Lists.newArrayList(); public RscSetUpdater(final Application.RunMode runMode, final ClusterBrowser browser, final Provider<ConstraintPHInfo> constraintPHInfoProvider, final Provider<PcmkRscSetsInfo> pcmkRscSetsInfoProvider) { this.runMode = runMode; this.browser = browser; this.constraintPHInfoProvider = constraintPHInfoProvider; this.pcmkRscSetsInfoProvider = pcmkRscSetsInfoProvider; this.crmGraph = browser.getCrmGraph(); } public void update(final List<RscSetConnectionData> newRscSetConnections) { findExistingPlaceholders(); for (final RscSetConnectionData newRscSetConnectionData : newRscSetConnections) { updateRscConnection(newRscSetConnectionData); } addNewPlaceholders(); } private void updateRscConnection(RscSetConnectionData newRscSetConnectionData) { Optional<ConstraintPHInfo> constraintPHInfo = updateExistingResourceSet(newRscSetConnectionData); if (!constraintPHInfo.isPresent()) { constraintPHInfo = addConstraintsToExistingPlaceholder(newRscSetConnectionData); } PcmkRscSetsInfo rscSetsInfo = null; if (constraintPHInfo.isPresent()) { rscSetsInfo = constraintPHInfo.get().getPcmkRscSetsInfo(); } if (!constraintPHInfo.isPresent() && !preNewCphis.isEmpty()) { constraintPHInfo = Optional.of(setOldPlaceholder(newRscSetConnectionData)); } if (!constraintPHInfo.isPresent()) { constraintPHInfo = Optional.of(createNewPlaceholder(newRscSetConnectionData, rscSetsInfo)); } addPlaceholder(newRscSetConnectionData, constraintPHInfo.get()); } private void addPlaceholder(final RscSetConnectionData newRscSetConnectionData, final ConstraintPHInfo constraintPHInfo) { serviceIsPresent.add(constraintPHInfo); if (newRscSetConnectionData.isColocation()) { addColocation(newRscSetConnectionData, constraintPHInfo); } else { addOrder(newRscSetConnectionData, constraintPHInfo); } if (Application.isLive(runMode)) { constraintPHInfo.setUpdated(false); constraintPHInfo.setNew(false); } } private Optional<ConstraintPHInfo> updateExistingResourceSet(RscSetConnectionData newRscSetConnectionData) { for (final Map.Entry<RscSetConnectionData, ConstraintPHInfo> phEntry : oldResourceSetToPlaceholder.entrySet()) { final RscSetConnectionData oldRscSetConnectionData = phEntry.getKey(); final ConstraintPHInfo placeholder = phEntry.getValue(); if (oldRscSetConnectionData == newRscSetConnectionData) { continue; } if (newRscSetConnectionData.equals(oldRscSetConnectionData) || newRscSetConnectionData.equalsAlthoughReversed(oldRscSetConnectionData)) { placeholder.setRscSetConnectionData(newRscSetConnectionData); return Optional.of(placeholder); } } return Optional.absent(); } private ConstraintPHInfo setOldPlaceholder(RscSetConnectionData newRscSetConnectionData) { ConstraintPHInfo constraintPHInfo; constraintPHInfo = preNewCphis.remove(0); oldResourceSetToPlaceholder.put(newRscSetConnectionData, constraintPHInfo); constraintPHInfo.setRscSetConnectionData(newRscSetConnectionData); return constraintPHInfo; } private ConstraintPHInfo createNewPlaceholder(RscSetConnectionData newRscSetConnectionData, PcmkRscSetsInfo rscSetsInfo) { ConstraintPHInfo constraintPHInfo; constraintPHInfo = constraintPHInfoProvider.get(); constraintPHInfo.init(this.browser, newRscSetConnectionData, ConstraintPHInfo.Preference.AND); if (rscSetsInfo == null) { rscSetsInfo = pcmkRscSetsInfoProvider.get(); rscSetsInfo.init(this.browser); } if (newRscSetConnectionData.isColocation()) { rscSetsInfo.addColocation(newRscSetConnectionData.getConstraintId(), constraintPHInfo); } else { rscSetsInfo.addOrder(newRscSetConnectionData.getConstraintId(), constraintPHInfo); } constraintPHInfo.setPcmkRscSetsInfo(rscSetsInfo); this.browser.addNameToServiceInfoHash(constraintPHInfo); newCphis.add(constraintPHInfo); /* have to add it later, so that ids are correct. */ oldResourceSetToPlaceholder.put(newRscSetConnectionData, constraintPHInfo); return constraintPHInfo; } private Optional<ConstraintPHInfo> addConstraintsToExistingPlaceholder(RscSetConnectionData newRscSetConnectionData) { for (final Map.Entry<RscSetConnectionData, ConstraintPHInfo> phEntry : oldResourceSetToPlaceholder.entrySet()) { final RscSetConnectionData oldRrcSetConnectionData = phEntry.getKey(); final ConstraintPHInfo placeholder = phEntry.getValue(); if (oldRrcSetConnectionData == newRscSetConnectionData) { return Optional.of(placeholder); } if (canReusePlaceholder(newRscSetConnectionData, oldRrcSetConnectionData, placeholder)) { return Optional.of(addContraintsToPlaceholder(newRscSetConnectionData, placeholder)); } } return Optional.absent(); } private ConstraintPHInfo addContraintsToPlaceholder(RscSetConnectionData newRscSetConnectionData, ConstraintPHInfo placeholder) { ConstraintPHInfo constraintPHInfo; constraintPHInfo = placeholder; constraintPHInfo.setRscSetConnectionData(newRscSetConnectionData); final PcmkRscSetsInfo rscSetsInfo = constraintPHInfo.getPcmkRscSetsInfo(); if (rscSetsInfo != null) { if (newRscSetConnectionData.isColocation()) { rscSetsInfo.addColocation(newRscSetConnectionData.getConstraintId(), constraintPHInfo); } else { rscSetsInfo.addOrder(newRscSetConnectionData.getConstraintId(), constraintPHInfo); } } return constraintPHInfo; } private boolean canReusePlaceholder(final RscSetConnectionData newRscSetConnectionData, final RscSetConnectionData oldRrcSetConnectionData, final ConstraintPHInfo placeholder) { return placeholder.isNew() || (newRscSetConnectionData.canUseSamePlaceholder(oldRrcSetConnectionData) && placeholder.sameConstraintId(newRscSetConnectionData)); } private void addColocation(final RscSetConnectionData newRscSetConnectionData, final ConstraintPHInfo constraintPHInfo) { final CrmXml.RscSet rscSet1 = newRscSetConnectionData.getRscSet1(); final CrmXml.RscSet rscSet2 = newRscSetConnectionData.getRscSet2(); if (rscSet1 != null) { addColocationsFromPlaceholder(newRscSetConnectionData, constraintPHInfo, rscSet1); } if (rscSet2 != null) { addColocationsToPlaceholder(newRscSetConnectionData, constraintPHInfo, rscSet2); } } private void addColocationsToPlaceholder(final RscSetConnectionData newRscSetConnectionData, final ConstraintPHInfo constraintPHInfo, final CrmXml.RscSet rscSet2) { for (final String rscId : rscSet2.getRscIds()) { final ServiceInfo si = this.browser.getServiceInfoFromCRMId(rscId); crmGraph.addColocation(newRscSetConnectionData.getConstraintId(), si, constraintPHInfo); } } private void addColocationsFromPlaceholder(final RscSetConnectionData newRscSetConnectionData, final ConstraintPHInfo constraintPHInfo, final CrmXml.RscSet rscSet1) { for (final String rscId : rscSet1.getRscIds()) { final ServiceInfo si = this.browser.getServiceInfoFromCRMId(rscId); crmGraph.addColocation(newRscSetConnectionData.getConstraintId(), constraintPHInfo, si); } } private void addOrder(RscSetConnectionData newRscSetConnectionData, ConstraintPHInfo constraintPHInfo) { final CrmXml.RscSet rscSet1 = newRscSetConnectionData.getRscSet1(); final CrmXml.RscSet rscSet2 = newRscSetConnectionData.getRscSet2(); if (rscSet1 != null) { addRscSetOrdersToPlaceholder(newRscSetConnectionData, rscSet1, constraintPHInfo); } if (rscSet2 != null) { addRscSetOrdersFromPlaceholder(newRscSetConnectionData, constraintPHInfo, rscSet2); } } private void addRscSetOrdersToPlaceholder(RscSetConnectionData newRscSetConnectionData, CrmXml.RscSet rscSet1, ConstraintPHInfo constraintPHInfo) { for (final String rscId : rscSet1.getRscIds()) { final ServiceInfo si = this.browser.getServiceInfoFromCRMId(rscId); crmGraph.addOrder(newRscSetConnectionData.getConstraintId(), si, constraintPHInfo); } } private void addRscSetOrdersFromPlaceholder(RscSetConnectionData newRscSetConnectionData, ConstraintPHInfo constraintPHInfo, CrmXml.RscSet rscSet2) { for (final String rscId : rscSet2.getRscIds()) { final ServiceInfo si = this.browser.getServiceInfoFromCRMId(rscId); crmGraph.addOrder(newRscSetConnectionData.getConstraintId(), constraintPHInfo, si); } } private void findExistingPlaceholders() { browser.lockNameToServiceInfo(); final Map<String, ServiceInfo> oldIdToInfoHash = browser.getNameToServiceInfoHash(ConstraintPHInfo.NAME); if (oldIdToInfoHash != null) { for (final Map.Entry<String, ServiceInfo> infoEntry : oldIdToInfoHash.entrySet()) { final ConstraintPHInfo cphi = (ConstraintPHInfo) infoEntry.getValue(); final RscSetConnectionData rdataOrd = cphi.getRscSetConnectionDataOrder(); final RscSetConnectionData rdataCol = cphi.getRscSetConnectionDataColocation(); if (cphi.isNew()) { preNewCphis.add(cphi); } if (rdataOrd != null && !rdataOrd.isEmpty()) { oldResourceSetToPlaceholder.put(rdataOrd, cphi); } if (rdataCol != null && !rdataCol.isEmpty()) { oldResourceSetToPlaceholder.put(rdataCol, cphi); } } } browser.unlockNameToServiceInfo(); } private void addNewPlaceholders() { for (final ConstraintPHInfo cphi : newCphis) { crmGraph.addConstraintPlaceholder(cphi, null /* pos */, Application.RunMode.LIVE); } } }