/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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 * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.services.activation; import org.simantics.db.Disposable; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.common.CommentMetadata; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.CommonDBUtils; import org.simantics.db.common.utils.Logger; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.layer0.utils.queries.QueryExecutor2; import org.simantics.layer0.utils.triggers.IActivation; import org.simantics.layer0.utils.triggers.IActivationManager; import org.simantics.layer0.utils.triggers.IModification; import org.simantics.layer0.utils.triggers.ITrigger; import org.simantics.operation.Layer0X; import org.simantics.utils.logging.TimeLogger; import org.simantics.utils.threads.logger.IThreadLogger; import org.simantics.utils.threads.logger.ThreadLogger; @SuppressWarnings("deprecation") // No replacement given so now way to fix this error. public class ActivationManager implements IActivationManager, Disposable { Session session; static IThreadLogger threadLogger = ThreadLogger.getInstance(); class Activation extends QueryExecutor2 implements IActivation { final boolean DEBUG = false; final boolean BREAK_INFINITE_ACTIVATION_LOOPS = true; /** * After {@value InfiniteLoop} the activation will be forcibly * deactivated if {@link #BREAK_INFINITE_ACTIVATION_LOOPS} is * true. */ final int INFINITE_LOOP_COUNT = 100; Resource resource; int transactionCount = 0; boolean disposed = false; boolean runOnce = false; public Activation(Resource resource) { this.resource = resource; } public void runOnceAndDeactivate() { runOnce = true; } @Override public void run(ReadGraph g) throws DatabaseException { // ITask task = threadLogger.begin("Activation.perform"); Layer0X L0X = Layer0X.getInstance(g); for(Resource r : g.getObjects(resource, L0X.HasTrigger)) if(calcModification(g, r) != null) execute(g, r); // task.finish(); } private IModification calcModification(ReadGraph g, Resource trigger) throws DatabaseException { // new Exception().printStackTrace(); //ITask task = ThreadLogger.getInstance().begin("Activation.calcModification"); IModification modi = g.syncRequest(g.adapt(trigger, ITrigger.class)); //task.finish(); return modi; } private WriteRequest getRequest(final Resource trigger) { return new WriteRequest() { @Override public void perform(WriteGraph g) throws DatabaseException { int count = 0; while (true) { CommonDBUtils.selectClusterSet(g, trigger); TimeLogger.log("ActivationManager: start calculating modification"); IModification modification = calcModification(g, trigger); TimeLogger.log("ActivationManager: finished calculating modification"); if (modification != null) ++count; else { if (count > 0) { CommentMetadata cm = g.getMetadata(CommentMetadata.class); String msg = "ActivationManager modification count=" + count; g.addMetadata(cm.add(msg)); if (DEBUG) System.out.println("DEBUG: " + msg); } if(runOnce) deactivate(); return; } if (BREAK_INFINITE_ACTIVATION_LOOPS) { if (count > INFINITE_LOOP_COUNT) { deactivate(); String msg = "Possible dynamic activation loop. Forcing break." + "Loop count was " + count + ". Activated resource was " + NameUtils.getURIOrSafeNameInternal(g, resource) + "."; System.out.println("WARNING: " + msg); throw new DatabaseException(msg); } } try { modification.perform(g); TimeLogger.log("ActivationManager: performed modification"); } catch (DatabaseException e) { deactivate(); throw e; } } } }; } private void executeOnce(WriteGraph graph, final Resource trigger) throws DatabaseException { getRequest(trigger).perform(graph); // graph.syncRequest(getRequest(trigger)); } private void execute(final ReadGraph graph, final Resource trigger) { graph.asyncRequest(getRequest(trigger)); } @Override public void deactivate() { disposed = true; } @Override public boolean isDisposed() { return disposed || session == null; } } public ActivationManager(Session session) { this.session = session; } @Override public IActivation activate(Resource r) { Session s = session; if (s == null) throw new IllegalStateException("ActivationManager is disposed"); Activation activation = new Activation(r); try { activation.execute(session); } catch (DatabaseException e) { Logger.defaultLogError(e); } return activation; } @Override public IActivation activate(WriteGraph graph, Resource r) throws DatabaseException { Session s = session; if (s == null) throw new IllegalStateException("ActivationManager is disposed"); Activation activation = new Activation(r); activation.execute(graph); return activation; } @Override public void activateOnce(Resource resource) { activate(resource).runOnceAndDeactivate(); } @Override public void activateOnce(WriteGraph graph, Resource resource) throws DatabaseException { Session s = session; if (s == null) throw new IllegalStateException("ActivationManager is disposed"); Layer0X L0X = Layer0X.getInstance(graph); for(Resource r : graph.getObjects(resource, L0X.HasTrigger)) { new Activation(resource).executeOnce(graph, r); } } @Override public void dispose() { session = null; } }