1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.ui.jobs;
14 import java.util.function.Consumer;
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.Status;
19 import org.eclipse.core.runtime.jobs.Job;
20 import org.simantics.DatabaseJob;
21 import org.simantics.Simantics;
22 import org.simantics.db.Session;
23 import org.simantics.db.exception.DatabaseException;
24 import org.simantics.db.layer0.util.SessionGarbageCollection;
25 import org.simantics.db.service.LifecycleSupport;
26 import org.simantics.utils.ui.ErrorLogger;
29 * @author Tuukka Lehtonen
31 public class SessionGarbageCollectorJob extends Job {
33 private static SessionGarbageCollectorJob instance;
35 public synchronized static SessionGarbageCollectorJob getInstance() {
37 instance = new SessionGarbageCollectorJob();
41 private static final boolean TRACE = false;
44 * At least 60 seconds between executions.
46 private static final long DEFAULT_QUIET_TIME = 5000;
49 private long quietTime;
50 private long userDefinedQuietTime;
52 private boolean enabled = true;
57 public SessionGarbageCollectorJob() {
58 this(DEFAULT_QUIET_TIME);
62 * @param delayBetweenExecutions
64 public SessionGarbageCollectorJob(long delayBetweenExecutions) {
65 super("Database Garbage Collector");
66 setPriority(Job.DECORATE);
68 // Hide job from users.
71 this.start = System.currentTimeMillis();
72 this.quietTime = delayBetweenExecutions;
73 this.userDefinedQuietTime = delayBetweenExecutions;
77 * Cancels the currently scheduled execution of this job and reschedules
78 * another execution after the current quiet time. This can be used for
79 * easily pushing GC back a bit while performing an operation during which
80 * it is not efficient to GC.
82 * @see #setQuietTime(long)
84 public void rescheduleAfterQuietTime() {
86 scheduleAfterQuietTime();
90 * Cancels the currently scheduled execution of this job and reschedules
91 * another with no delay. This can be used for immediate forced execution of
94 public void rescheduleNow() {
103 public SessionGarbageCollectorJob setEnabled(boolean enabled) {
104 this.enabled = enabled;
109 // * @param quietTime quiet time between collections in
112 // public SessionGarbageCollectorJob setQuietTime(long quietTime) {
113 // this.quietTime = quietTime;
118 * Schedules this job after the currently set quiet time.
120 * @see #setQuietTime(long)
122 public void scheduleAfterQuietTime() {
127 public boolean shouldSchedule() {
132 public boolean shouldRun() {
135 long t = System.currentTimeMillis();
136 System.out.println("GC disabled, not running @ " + ((double) (t - start) * 1e-3) + " seconds");
143 * Only invoked with actual errors, not <code>null</code> values.
145 Consumer<DatabaseException> errorCallback = e -> ErrorLogger.defaultLogError(e);
148 protected IStatus run(IProgressMonitor monitor) {
149 long interval = quietTime;
151 Session session = Simantics.peekSession();
153 return Status.CANCEL_STATUS;
154 LifecycleSupport lfs = session.peekService(LifecycleSupport.class);
155 if (lfs == null || lfs.isClosed() || lfs.isClosing())
156 return Status.CANCEL_STATUS;
158 // Never run while a heavy database job is in progress.
159 if (DatabaseJob.inProgress()) {
160 // Schedule again in at most 10 seconds instead of
161 // waiting for the whole quiet time period again.
162 interval = Math.min(10, quietTime);
163 return Status.CANCEL_STATUS;
166 // // Don't run if there are currently write requests in progress
167 // TransactionSupport ts = session.getService(TransactionSupport.class);
168 // if (ts.getWriteCount() > 0) {
170 // long t = System.currentTimeMillis();
171 // System.out.println("Write in progress, no GC @ " + ((double) (t - start) * 1e-3) + " seconds");
173 // return Status.CANCEL_STATUS;
176 long begin = System.currentTimeMillis();
178 System.out.println("running GC @ " + ((double) (begin - start) * 1e-3) + " seconds");
181 boolean busy = SessionGarbageCollection.gc(monitor, session, true, errorCallback);
183 quietTime = Math.max((3*quietTime)/4, 100);
185 if(quietTime < userDefinedQuietTime)
186 quietTime = Math.min(userDefinedQuietTime, (long)(1.2*quietTime));
191 System.err.println("Session GC ended busy. New quiet time is " + quietTime);
193 // This quiet time might have been adjusted in GC
194 interval = quietTime;
196 long intermediate = System.currentTimeMillis();
198 // Clean up heap of all garbage left behind by SessionGarbageCollection
202 //long end = System.currentTimeMillis();
203 //System.out.println("Session.GC " + (intermediate - begin) + "ms, System.GC " + (end-intermediate) + "ms, total " + (end - begin) + "ms");
204 System.out.println("Session.GC " + (intermediate - begin) + "ms");
207 // Reschedule after a quiet period.
208 return Status.OK_STATUS;