/* * Copyright (c) 2017 Serro LLC. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.nic.common.transaction.service.lifecycle; import org.opendaylight.nic.common.transaction.service.IntentService; import org.opendaylight.nic.common.transaction.service.action.add.IntentAddAction; import org.opendaylight.nic.common.transaction.service.action.remove.IntentRemoveAction; import org.opendaylight.nic.common.transaction.service.renderer.RendererService; import org.opendaylight.nic.common.transaction.utils.CommonUtils; import org.opendaylight.nic.engine.IntentStateMachineExecutorService; import org.opendaylight.nic.utils.EventType; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import static org.opendaylight.nic.utils.EventType.*; /** * Created by yrineu on 07/04/17. */ public class IntentLifeCycleManagement implements IntentLifeCycleRegister, IntentLifeCycleService { private abstract class EventExecutor implements IntentActionListener { abstract void doExecute(String id); } private final Set<IntentLifeCycleListener> lifeCycleListeners; private final Map<EventType, EventExecutor> executorByEvent; private final IntentStateMachineExecutorService stateMachineExecutorService; private final RendererService rendererService; protected IntentActionRegister intentAddActionRegister; private IntentService intentService; public IntentLifeCycleManagement(final IntentStateMachineExecutorService stateMachineExecutorService, final RendererService rendererService) { this.stateMachineExecutorService = stateMachineExecutorService; this.lifeCycleListeners = ConcurrentHashMap.newKeySet(); this.executorByEvent = new HashMap<>(); this.rendererService = rendererService; //TODO: Remove this too logic from this constructor populateEventHandler(); } private void populateEventHandler() { final EventExecutor INTENT_CREATED_EXECUTOR = new EventExecutor() { @Override public void doExecute(String id) { intentService.clearActionListerList(); intentService.start(id); intentAddActionRegister.register(id, this); stateMachineExecutorService.createTransaction(id, INTENT_CREATED); CommonUtils.waitUnlock(); notifyStarted(); } @Override public void proceedToNext(String id) { executorByEvent.get(INTENT_BEING_ADDED).doExecute(id); } @Override public void proceedToNextFailed(String id) { //DO_NOTHING } }; final EventExecutor INTENT_BEING_ADDED_EXECUTOR = new EventExecutor() { @Override void doExecute(String id) { intentService.clearActionListerList(); CommonUtils.waitUnlock(); intentAddActionRegister.register(id, this); stateMachineExecutorService.goToNextTransaction(id, INTENT_BEING_ADDED); notifyToProceed(); } @Override public void proceedToNext(String id) { CommonUtils.waitUnlock(); lifeCycleListeners.clear(); stateMachineExecutorService.goToNextTransaction(id, INTENT_ADDED_WITH_SUCCESS); } @Override public void proceedToNextFailed(String id) { CommonUtils.waitUnlock(); stateMachineExecutorService.goToNextTransaction(id, INTENT_ADDED_ERROR); boolean canEvaluateAttempt = stateMachineExecutorService.canEvaluateAttempt(id, INTENT_ADD_ATTEMPT); if (canEvaluateAttempt) { CommonUtils.waitUnlock(); stateMachineExecutorService.goToNextTransaction(id, INTENT_ADD_ATTEMPT); notifyToProceed(); } else { stateMachineExecutorService.goToNextTransaction(id, INTENT_ADD_RETRY_WITH_MAX_ATTEMPTS); executorByEvent.get(INTENT_DISABLE).doExecute(id); } } }; final EventExecutor INTENT_REMOVED_EXECUTOR = new EventExecutor() { @Override void doExecute(String id) { intentService.clearActionListerList(); intentService.start(id); intentAddActionRegister.register(id, this); stateMachineExecutorService.goToNextTransaction(id, INTENT_BEING_REMOVED); notifyToProceed(); } @Override public void proceedToNext(String id) { CommonUtils.waitUnlock(); lifeCycleListeners.clear(); stateMachineExecutorService.goToNextTransaction(id, INTENT_REMOVED_WITH_SUCCESS); } @Override public void proceedToNextFailed(String id) { CommonUtils.waitUnlock(); stateMachineExecutorService.goToNextTransaction(id, INTENT_REMOVE_ERROR); boolean canEvaluateAttempt = stateMachineExecutorService.canEvaluateAttempt(id, INTENT_REMOVE_ATTEMPT); if (canEvaluateAttempt) { stateMachineExecutorService.goToNextTransaction(id, INTENT_REMOVE_ATTEMPT); notifyToProceed(); } else { stateMachineExecutorService.goToNextTransaction(id, INTENT_REMOVE_RETRY_WITH_MAX_ATTEMPTS); executorByEvent.get(INTENT_DISABLE).doExecute(id); } } }; final EventExecutor INTENT_DISABLE_EXECUTOR = new EventExecutor() { @Override void doExecute(String id) { intentService.clearActionListerList(); CommonUtils.waitUnlock(); intentAddActionRegister.register(id, this); stateMachineExecutorService.goToNextTransaction(id, INTENT_BEING_DISABLED); notifyToStopProcess(); } @Override public void proceedToNext(String id) { CommonUtils.waitUnlock(); lifeCycleListeners.clear(); stateMachineExecutorService.goToNextTransaction(id, INTENT_DISABLED); } @Override public void proceedToNextFailed(String id) { CommonUtils.waitUnlock(); lifeCycleListeners.clear(); stateMachineExecutorService.goToNextTransaction(id, INTENT_DISABLED_WITH_INCONSISTENCIES); } }; executorByEvent.put(INTENT_CREATED, INTENT_CREATED_EXECUTOR); executorByEvent.put(INTENT_BEING_ADDED, INTENT_BEING_ADDED_EXECUTOR); executorByEvent.put(INTENT_REMOVED, INTENT_REMOVED_EXECUTOR); executorByEvent.put(INTENT_DISABLE, INTENT_DISABLE_EXECUTOR); } @Override public void startTransaction(final String id, final EventType eventType) { switch (eventType) { case INTENT_CREATED: this.intentService = new IntentAddAction(this, rendererService); this.intentAddActionRegister = (IntentActionRegister) intentService; executorByEvent.get(INTENT_CREATED).doExecute(id); break; case INTENT_REMOVED: this.intentService = new IntentRemoveAction(this, rendererService); this.intentAddActionRegister = (IntentActionRegister) intentService; executorByEvent.get(INTENT_REMOVED).doExecute(id); break; } } @Override public void register(IntentLifeCycleListener listener) { lifeCycleListeners.add(listener); } @Override public void unregister(IntentLifeCycleListener listener) { lifeCycleListeners.remove(listener); } private void notifyStarted() { lifeCycleListeners.forEach(listener -> listener.transactionStarted()); } private void notifyToProceed() { lifeCycleListeners.forEach(listener -> listener.proceedExecution()); } private void notifyToStopProcess() { lifeCycleListeners.forEach(listener -> listener.stopExecution()); } }