X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=bundles%2Forg.simantics.ui%2Fsrc%2Forg%2Fsimantics%2Fui%2Fjobs%2FSessionGarbageCollectorJob.java;fp=bundles%2Forg.simantics.ui%2Fsrc%2Forg%2Fsimantics%2Fui%2Fjobs%2FSessionGarbageCollectorJob.java;h=1805d0dab4b451f2a345715a63b4ff79138a850e;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=c847ddfecfe36b12c4c0fc4e59893078af829498;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.ui/src/org/simantics/ui/jobs/SessionGarbageCollectorJob.java b/bundles/org.simantics.ui/src/org/simantics/ui/jobs/SessionGarbageCollectorJob.java index c847ddfec..1805d0dab 100644 --- a/bundles/org.simantics.ui/src/org/simantics/ui/jobs/SessionGarbageCollectorJob.java +++ b/bundles/org.simantics.ui/src/org/simantics/ui/jobs/SessionGarbageCollectorJob.java @@ -1,215 +1,215 @@ -/******************************************************************************* - * Copyright (c) 2007, 2011 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.ui.jobs; - -import java.util.function.Consumer; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.simantics.DatabaseJob; -import org.simantics.Simantics; -import org.simantics.db.Session; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.util.SessionGarbageCollection; -import org.simantics.db.service.LifecycleSupport; -import org.simantics.utils.ui.ErrorLogger; - -/** - * @author Tuukka Lehtonen - */ -public class SessionGarbageCollectorJob extends Job { - - private static SessionGarbageCollectorJob instance; - - public synchronized static SessionGarbageCollectorJob getInstance() { - if (instance == null) - instance = new SessionGarbageCollectorJob(); - return instance; - } - - private static final boolean TRACE = false; - - /** - * At least 60 seconds between executions. - */ - private static final long DEFAULT_QUIET_TIME = 5000; - - private long start; - private long quietTime; - private long userDefinedQuietTime; - - private boolean enabled = true; - - /** - * - */ - public SessionGarbageCollectorJob() { - this(DEFAULT_QUIET_TIME); - } - - /** - * @param delayBetweenExecutions - */ - public SessionGarbageCollectorJob(long delayBetweenExecutions) { - super("Database Garbage Collector"); - setPriority(Job.DECORATE); - - // Hide job from users. - setSystem(true); - - this.start = System.currentTimeMillis(); - this.quietTime = delayBetweenExecutions; - this.userDefinedQuietTime = delayBetweenExecutions; - } - - /** - * Cancels the currently scheduled execution of this job and reschedules - * another execution after the current quiet time. This can be used for - * easily pushing GC back a bit while performing an operation during which - * it is not efficient to GC. - * - * @see #setQuietTime(long) - */ - public void rescheduleAfterQuietTime() { - cancel(); - scheduleAfterQuietTime(); - } - - /** - * Cancels the currently scheduled execution of this job and reschedules - * another with no delay. This can be used for immediate forced execution of - * session GC. - */ - public void rescheduleNow() { - cancel(); - schedule(); - } - - /** - * @param enabled - * @return - */ - public SessionGarbageCollectorJob setEnabled(boolean enabled) { - this.enabled = enabled; - return this; - } - -// /** -// * @param quietTime quiet time between collections in -// * milliseconds -// */ -// public SessionGarbageCollectorJob setQuietTime(long quietTime) { -// this.quietTime = quietTime; -// return this; -// } - - /** - * Schedules this job after the currently set quiet time. - * - * @see #setQuietTime(long) - */ - public void scheduleAfterQuietTime() { - schedule(quietTime); - } - - @Override - public boolean shouldSchedule() { - return enabled; - } - - @Override - public boolean shouldRun() { - if (TRACE) { - if (!enabled) { - long t = System.currentTimeMillis(); - System.out.println("GC disabled, not running @ " + ((double) (t - start) * 1e-3) + " seconds"); - } - } - return enabled; - } - - /** - * Only invoked with actual errors, not null values. - */ - Consumer errorCallback = e -> ErrorLogger.defaultLogError(e); - - @Override - protected IStatus run(IProgressMonitor monitor) { - long interval = quietTime; - try { - Session session = Simantics.peekSession(); - if (session == null) - return Status.CANCEL_STATUS; - LifecycleSupport lfs = session.peekService(LifecycleSupport.class); - if (lfs == null || lfs.isClosed() || lfs.isClosing()) - return Status.CANCEL_STATUS; - - // Never run while a heavy database job is in progress. - if (DatabaseJob.inProgress()) { - // Schedule again in at most 10 seconds instead of - // waiting for the whole quiet time period again. - interval = Math.min(10, quietTime); - return Status.CANCEL_STATUS; - } - -// // Don't run if there are currently write requests in progress -// TransactionSupport ts = session.getService(TransactionSupport.class); -// if (ts.getWriteCount() > 0) { -// if (TRACE) { -// long t = System.currentTimeMillis(); -// System.out.println("Write in progress, no GC @ " + ((double) (t - start) * 1e-3) + " seconds"); -// } -// return Status.CANCEL_STATUS; -// } - - long begin = System.currentTimeMillis(); - if (TRACE) { - System.out.println("running GC @ " + ((double) (begin - start) * 1e-3) + " seconds"); - } - - boolean busy = SessionGarbageCollection.gc(monitor, session, true, errorCallback); - if(busy) { - quietTime = Math.max((3*quietTime)/4, 100); - } else { - if(quietTime < userDefinedQuietTime) - quietTime = Math.min(userDefinedQuietTime, (long)(1.2*quietTime)); - } - - if (TRACE) - if(busy) - System.err.println("Session GC ended busy. New quiet time is " + quietTime); - - // This quiet time might have been adjusted in GC - interval = quietTime; - - long intermediate = System.currentTimeMillis(); - - // Clean up heap of all garbage left behind by SessionGarbageCollection - //System.gc(); - - if (TRACE) { - //long end = System.currentTimeMillis(); - //System.out.println("Session.GC " + (intermediate - begin) + "ms, System.GC " + (end-intermediate) + "ms, total " + (end - begin) + "ms"); - System.out.println("Session.GC " + (intermediate - begin) + "ms"); - } - - // Reschedule after a quiet period. - return Status.OK_STATUS; - } finally { - schedule(interval); - monitor.done(); - } - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2011 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.ui.jobs; + +import java.util.function.Consumer; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.simantics.DatabaseJob; +import org.simantics.Simantics; +import org.simantics.db.Session; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.util.SessionGarbageCollection; +import org.simantics.db.service.LifecycleSupport; +import org.simantics.utils.ui.ErrorLogger; + +/** + * @author Tuukka Lehtonen + */ +public class SessionGarbageCollectorJob extends Job { + + private static SessionGarbageCollectorJob instance; + + public synchronized static SessionGarbageCollectorJob getInstance() { + if (instance == null) + instance = new SessionGarbageCollectorJob(); + return instance; + } + + private static final boolean TRACE = false; + + /** + * At least 60 seconds between executions. + */ + private static final long DEFAULT_QUIET_TIME = 5000; + + private long start; + private long quietTime; + private long userDefinedQuietTime; + + private boolean enabled = true; + + /** + * + */ + public SessionGarbageCollectorJob() { + this(DEFAULT_QUIET_TIME); + } + + /** + * @param delayBetweenExecutions + */ + public SessionGarbageCollectorJob(long delayBetweenExecutions) { + super("Database Garbage Collector"); + setPriority(Job.DECORATE); + + // Hide job from users. + setSystem(true); + + this.start = System.currentTimeMillis(); + this.quietTime = delayBetweenExecutions; + this.userDefinedQuietTime = delayBetweenExecutions; + } + + /** + * Cancels the currently scheduled execution of this job and reschedules + * another execution after the current quiet time. This can be used for + * easily pushing GC back a bit while performing an operation during which + * it is not efficient to GC. + * + * @see #setQuietTime(long) + */ + public void rescheduleAfterQuietTime() { + cancel(); + scheduleAfterQuietTime(); + } + + /** + * Cancels the currently scheduled execution of this job and reschedules + * another with no delay. This can be used for immediate forced execution of + * session GC. + */ + public void rescheduleNow() { + cancel(); + schedule(); + } + + /** + * @param enabled + * @return + */ + public SessionGarbageCollectorJob setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + +// /** +// * @param quietTime quiet time between collections in +// * milliseconds +// */ +// public SessionGarbageCollectorJob setQuietTime(long quietTime) { +// this.quietTime = quietTime; +// return this; +// } + + /** + * Schedules this job after the currently set quiet time. + * + * @see #setQuietTime(long) + */ + public void scheduleAfterQuietTime() { + schedule(quietTime); + } + + @Override + public boolean shouldSchedule() { + return enabled; + } + + @Override + public boolean shouldRun() { + if (TRACE) { + if (!enabled) { + long t = System.currentTimeMillis(); + System.out.println("GC disabled, not running @ " + ((double) (t - start) * 1e-3) + " seconds"); + } + } + return enabled; + } + + /** + * Only invoked with actual errors, not null values. + */ + Consumer errorCallback = e -> ErrorLogger.defaultLogError(e); + + @Override + protected IStatus run(IProgressMonitor monitor) { + long interval = quietTime; + try { + Session session = Simantics.peekSession(); + if (session == null) + return Status.CANCEL_STATUS; + LifecycleSupport lfs = session.peekService(LifecycleSupport.class); + if (lfs == null || lfs.isClosed() || lfs.isClosing()) + return Status.CANCEL_STATUS; + + // Never run while a heavy database job is in progress. + if (DatabaseJob.inProgress()) { + // Schedule again in at most 10 seconds instead of + // waiting for the whole quiet time period again. + interval = Math.min(10, quietTime); + return Status.CANCEL_STATUS; + } + +// // Don't run if there are currently write requests in progress +// TransactionSupport ts = session.getService(TransactionSupport.class); +// if (ts.getWriteCount() > 0) { +// if (TRACE) { +// long t = System.currentTimeMillis(); +// System.out.println("Write in progress, no GC @ " + ((double) (t - start) * 1e-3) + " seconds"); +// } +// return Status.CANCEL_STATUS; +// } + + long begin = System.currentTimeMillis(); + if (TRACE) { + System.out.println("running GC @ " + ((double) (begin - start) * 1e-3) + " seconds"); + } + + boolean busy = SessionGarbageCollection.gc(monitor, session, true, errorCallback); + if(busy) { + quietTime = Math.max((3*quietTime)/4, 100); + } else { + if(quietTime < userDefinedQuietTime) + quietTime = Math.min(userDefinedQuietTime, (long)(1.2*quietTime)); + } + + if (TRACE) + if(busy) + System.err.println("Session GC ended busy. New quiet time is " + quietTime); + + // This quiet time might have been adjusted in GC + interval = quietTime; + + long intermediate = System.currentTimeMillis(); + + // Clean up heap of all garbage left behind by SessionGarbageCollection + //System.gc(); + + if (TRACE) { + //long end = System.currentTimeMillis(); + //System.out.println("Session.GC " + (intermediate - begin) + "ms, System.GC " + (end-intermediate) + "ms, total " + (end - begin) + "ms"); + System.out.println("Session.GC " + (intermediate - begin) + "ms"); + } + + // Reschedule after a quiet period. + return Status.OK_STATUS; + } finally { + schedule(interval); + monitor.done(); + } + } + +}