All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ogema.resourcemanager.impl.transaction.actions.ActivationAction Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2011-2018 Fraunhofer-Gesellschaft zur Förderung der angewandten Wissenschaften e.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ogema.resourcemanager.impl.transaction.actions;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import java.util.Queue;

import org.ogema.core.model.Resource;
import org.ogema.core.resourcemanager.ResourceOperationException.Type;
import org.ogema.core.resourcemanager.VirtualResourceException;
import org.ogema.resourcemanager.impl.transaction.AtomicAction;

public class ActivationAction implements AtomicAction {
	
	private final Resource target;
	private final boolean activate;
	private final boolean recursive;
	private final boolean create; // ignore for deactivation action
	private boolean oldState = false; // for rollback
	private boolean done;
	private boolean setBack;
	private final Queue subactions = new ArrayDeque<>();
	private final Deque subactionsDone = new ArrayDeque<>();
	
	public ActivationAction(Resource target, boolean activate, boolean recursive, boolean create) {
		Objects.requireNonNull(target);
		this.target = target;
		this.activate = activate;
		this.recursive = recursive;
		this.create = create;
	}
	
	private void buildActionsTree() {
		if (create && activate) {
			subactions.add(new CreationAction(target));
		}
		if (!recursive)
			return;
		List subs = target.getDirectSubResources(true);
		for (Resource sub: subs) {
			subactions.add(new ActivationAction(sub, activate, false, false));
		}
	}
	
	private void executeSubActions() throws Exception {
		AtomicAction action;
		while ((action = subactions.poll()) != null) {
			subactionsDone.add(action); // add this immediately, so we'll try to rollback this action even if it fails
			action.execute();
		}
	}
	
	private void rollbackSubactions() throws IllegalStateException {
		AtomicAction action;
		while ((action = subactionsDone.pollLast()) != null) {
			try {
				action.rollback();
			} catch (Exception e) {
				continue;
			}
		}
	}
	
	@Override
	public void execute() throws Exception {
		if (done || setBack)
			throw new IllegalStateException("Transaction has been executed already");
		done = true;
		buildActionsTree(); // we cannot do this earlier, e.g. in the constructor, since at that time no resource lock is held
		executeSubActions();
		if (!target.exists())
			throw new VirtualResourceException("Target resource " + target + " is virtual");
		oldState = target.isActive();
		if (activate)
			target.activate(false);
		else
			target.deactivate(false);
	}

	@Override
	public void rollback() throws IllegalStateException {
		if (!done)
			throw new IllegalStateException("Transaction has not been executed yet, cannot set back");
		if (setBack)
			throw new IllegalStateException("Transaction has been rolled back already");
		setBack =true;
//		if (!existed) {
//			target.delete();
//			return;
//		}
		try {
			if (oldState && !activate)
				target.activate(false);
			else if (!oldState && activate)
				target.deactivate(false);
		} catch (Exception e) {
			// we better ignore this... e.g. it could fail due to missing permissions, in which case already the original action should have failed
		}
		rollbackSubactions();
	}

	@Override
	public boolean requiresStructureWriteLock() {
		return true;
	}

	@Override
	public boolean requiresCommitWriteLock() {
		return false; // XXX?
	}

	@Override
	public Type getType() {
		return activate ? Type.ACTIVATE : Type.DEACTIVATE;
	}

	@Override
	public Resource getSource() {
		return target;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy