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;h=d987c344431ae39d53316f5dee9044c73eb9e748;hb=23f635e618eac5952aa6fe400b81c0cb8260ff01;hp=c847ddfecfe36b12c4c0fc4e59893078af829498;hpb=969bd23cab98a79ca9101af33334000879fb60c5;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..d987c3444 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,218 @@
-/*******************************************************************************
- * 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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class SessionGarbageCollectorJob extends Job {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SessionGarbageCollectorJob.class);
+ 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();
+ LOGGER.info("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) {
+ LOGGER.info("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)
+ LOGGER.info("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");
+ LOGGER.info("Session.GC " + (intermediate - begin) + "ms");
+ }
+
+ // Reschedule after a quiet period.
+ return Status.OK_STATUS;
+ } finally {
+ schedule(interval);
+ monitor.done();
+ }
+ }
+
+}