/******************************************************************************* * 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.db.layer0.util; import java.util.function.Consumer; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.simantics.db.ReadGraph; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.ClusterControl; import org.simantics.db.service.LifecycleSupport; import org.simantics.db.service.QueryControl; import org.simantics.utils.DataContainer; /** * @author Tuukka Lehtonen */ public class SessionGarbageCollection { /** * collect everything possible, default target is 0 queries. */ private static int DEFAULT_ALLOWED_TIME = 300; public static int getDefaultQueryTarget() { return DEFAULT_ALLOWED_TIME; } public static void setDefaultAllowedTime(int a) { DEFAULT_ALLOWED_TIME = a; } /** * Default maximum cluster memory consumption target is 32MB. */ private static int DEFAULT_CLUSTER_TARGET = -1; public static int getDefaultClusterTarget() { return DEFAULT_CLUSTER_TARGET; } public static void setDefaultClusterTarget(int a) { DEFAULT_CLUSTER_TARGET = a; } /** * @param monitor null if progress monitor not available * @param session the session to GC * @param sync true to block until gc is completed * @param errorCallback callback for any errors occuring during the * operation or null to ignore errors */ public static boolean gc(IProgressMonitor monitor, Session session, boolean sync, final Consumer errorCallback) { long took = gc(monitor, session, sync, errorCallback, DEFAULT_ALLOWED_TIME, DEFAULT_CLUSTER_TARGET); return ((16*took) / DEFAULT_ALLOWED_TIME) > 15; } public static void gc(ReadGraph graph, final int allowedTimeInMs, final int clusterTarget) throws DatabaseException { doIt(null, graph, allowedTimeInMs, clusterTarget); } public static void gc(IProgressMonitor monitor, ReadGraph graph, final int allowedTimeInMs, final int clusterTarget) throws DatabaseException { doIt(monitor, graph, allowedTimeInMs, clusterTarget); } private static void doIt(IProgressMonitor _monitor, ReadGraph graph, final int allowedTimeInMs, final int clusterTarget) { if(_monitor == null) _monitor = new NullProgressMonitor(); QueryControl qc = graph.getService(QueryControl.class); ClusterControl cc = graph.getService(ClusterControl.class); _monitor.beginTask("Collect clusters", IProgressMonitor.UNKNOWN); //cc.gc(graph, clusterTarget); if(clusterTarget == -1) { int used = cc.used(); //System.err.println("session gc, cluster use = " + used); int baseline = 32*(1<<20); if(used > baseline) { int dynamicTarget = (int)(0.95 * (used-baseline)) + baseline; cc.gc(graph, dynamicTarget); } } else { cc.gc(graph, clusterTarget); } _monitor.beginTask("Collect queries", IProgressMonitor.UNKNOWN); qc.gc(graph, allowedTimeInMs); } /** * @param monitor * @param session * @param sync * @param errorCallback */ /** * @param monitor null if progress monitor not available * @param session the session to GC * @param sync true to block until gc is completed * @param errorCallback callback for any errors occuring during the * operation or null to ignore errors * @param allowedTimeInMs the time allowed for query collection in ms * @param clusterTarget target for the maximum amount of memory in bytes to * be consumed by cluster caches after collection. */ public static long gc(IProgressMonitor monitor, Session session, boolean sync, final Consumer errorCallback, final int allowedTimeInMs, final int clusterTarget) { if (monitor == null) monitor = new NullProgressMonitor(); final IProgressMonitor _monitor = monitor; if (session == null) throw new NullPointerException("null session"); final DataContainer took = new DataContainer(0L); WriteRequest request = new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { long start = System.nanoTime(); doIt(_monitor, graph, allowedTimeInMs, clusterTarget); long duration = System.nanoTime()-start; took.set((long)(duration*1e-6)); } }; LifecycleSupport lfs = session.peekService(LifecycleSupport.class); if (lfs == null || lfs.isClosed() || lfs.isClosing()) return 0L; if (sync) { try { session.syncRequest(request); } catch (DatabaseException e) { if (errorCallback != null) errorCallback.accept(e); else Logger.defaultLogError(e); } } else { session.asyncRequest(request, e -> { if (e != null) { if (errorCallback != null) errorCallback.accept(e); else Logger.defaultLogError(e); } }); } return took.get(); } }