Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions api/src/org/labkey/api/ApiModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@
import org.labkey.api.module.ModuleLoader;
import org.labkey.api.module.ModuleLoader.StartupPropertyStartupListener;
import org.labkey.api.module.ModuleXml;
import org.labkey.api.module.TomcatVersion;
import org.labkey.api.query.AbstractQueryUpdateService;
import org.labkey.api.query.AliasManager;
import org.labkey.api.query.DetailsURL;
Expand Down Expand Up @@ -522,7 +521,6 @@ public void registerServlets(ServletContext servletCtx)
Table.TestCase.class,
TableSelectorTestCase.class,
TempTableInClauseGenerator.TestCase.class,
TomcatVersion.TestCase.class,
URLHelper.TestCase.class,
UserManager.TestCase.class,
ViewCategoryManager.TestCase.class,
Expand Down
147 changes: 47 additions & 100 deletions api/src/org/labkey/api/data/TempTableTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,77 @@

package org.labkey.api.data;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.labkey.api.cache.CacheManager;
import org.labkey.api.data.dialect.SqlDialect;
import org.labkey.api.util.FileUtil;
import org.labkey.api.util.ShutdownListener;
import org.labkey.api.util.logging.LogHelper;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.ref.Cleaner;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* User: Matthew
* Date: May 4, 2006
* Time: 7:27:50 PM
*/
public class TempTableTracker extends WeakReference<Object>
public class TempTableTracker
{
private static final Logger _log = LogManager.getLogger(TempTableTracker.class);
private static final Logger _log = LogHelper.getLogger(TempTableTracker.class, "Manages temp tables and their deletion");
private static final String LOGFILE = "CPAS_sqlTempTables.log";
private static final Map<String, TempTableTracker> createdTableNames = new TreeMap<>();
private static final ReferenceQueue<Object> cleanupQueue = new ReferenceQueue<>();
private static final Cleaner cleaner = Cleaner.create();

private static RandomAccessFile tempTableLog = null;

private final DbSchema schema;
private final String schemaName;
private final String tableName;
private final String qualifiedName;
private final Cleaner.Cleanable cleanable;
private final CleanupState state;

private boolean deleted = false;
private static class CleanupState implements Runnable
{
private final DbSchema schema;
private final String tableName;
private final String qualifiedName;
private final String schemaName;
private boolean deleted = false;

private CleanupState(DbSchema schema, String tableName, String qualifiedName, String schemaName)
{
this.schema = schema;
this.tableName = tableName;
this.qualifiedName = qualifiedName;
this.schemaName = schemaName;
}

@Override
public void run()
{
if (!deleted)
{
_log.debug("Deleting table " + schema.getName() + "." + tableName);
schema.dropTableIfExists(tableName);

deleted = true;
untrack(qualifiedName, schemaName, tableName);
}
}
}

private TempTableTracker(DbSchema schema, String tableName, Object ref)
{
super(ref, cleanupQueue);
this.schema = schema;
this.schemaName = schema.getName();
this.tableName = tableName;
this.qualifiedName = this.schemaName + "." + this.tableName;
this.state = new CleanupState(schema, tableName, qualifiedName, schemaName);
cleanable = cleaner.register(ref, state);
}


Expand All @@ -71,21 +95,19 @@ private TempTableTracker(String schemaName, String tableName, Object ref)
this(DbSchema.get(schemaName), tableName, ref); // TODO: Treat as provisioned?
}

private static final Object initlock = new Object();
private static final Object LOCK = new Object();
private static boolean initialized = false;

// make sure temp table tracker is initialized
public static void init()
{
synchronized(initlock)
synchronized(LOCK)
{
if (!initialized)
{
initialized = true;
synchronizeLog(true);
purgeTempSchema();
tempTableThread.setDaemon(true);
tempTableThread.start();
}
}
}
Expand Down Expand Up @@ -120,56 +142,22 @@ private static TempTableTracker track(TempTableTracker ttt)
}
}


private DbSchema getSchema()
{
return schema;
}


public synchronized void delete()
{
if (deleted)
return;

sqlDelete();

deleted = true;
untrack();
}


private boolean sqlDelete()
{
DbSchema schema = getSchema();
_log.debug("Deleting table " + schema.getName() + "." + tableName);
schema.dropTableIfExists(tableName);
return true;
cleanable.clean();
}


@Override
protected void finalize() throws Throwable
{
if (!deleted)
_log.error("finalizing undeleted TempTableTracker: " + qualifiedName);
super.finalize();
}


private void untrack()
private static void untrack(String qualifiedName, String schemaName, String tableName)
{
_log.debug("untrack(" + qualifiedName + ")");

synchronized(createdTableNames)
{
var ttt = createdTableNames.remove(qualifiedName);
createdTableNames.remove(qualifiedName);
appendToLog("-" + schemaName + "\t" + tableName + "\n");

if (createdTableNames.isEmpty() || System.currentTimeMillis() > lastSync + CacheManager.DAY)
synchronizeLog(false);

ttt.clear();
}
}

Expand Down Expand Up @@ -267,7 +255,7 @@ else if (s.charAt(0) == '-')
tempTableLog.setLength(0);
for (TempTableTracker ttt : createdTableNames.values())
{
if (!ttt.deleted)
if (!ttt.state.deleted)
appendToLog("+" + ttt.schemaName + "\t" + ttt.tableName + "\n");
}
}
Expand All @@ -285,47 +273,12 @@ else if (s.charAt(0) == '-')

static final TempTableThread tempTableThread = new TempTableThread();

static class TempTableThread extends Thread implements ShutdownListener
public static class TempTableThread implements ShutdownListener
{
AtomicBoolean _shutdown = new AtomicBoolean(false);

TempTableThread()
{
super("Temp table cleanup");
setDaemon(true);
}

@Override
public void run()
{
while (true)
{
try
{
Reference<?> r = _shutdown.get() ? cleanupQueue.poll() : cleanupQueue.remove();
if (_shutdown.get() && r == null)
return;
//noinspection RedundantCast
TempTableTracker t = (TempTableTracker)(Object)r;
t.delete();
}
catch (InterruptedException x)
{
_log.debug("interrupted");
}
catch (Throwable x)
{
_log.error("unexpected error", x);
}
}
}


@Override
public void shutdownPre()
public String getName()
{
_shutdown.set(true);
interrupt();
return "Temp table cleanup";
}

@Override
Expand All @@ -335,16 +288,10 @@ public void shutdownStarted()
{
for (TempTableTracker ttt : createdTableNames.values())
{
ttt.sqlDelete();
ttt.deleted = true;
ttt.state.run();
}
}

try
{
join(5000);
}
catch (InterruptedException ignored) {}
synchronizeLog(false);
}
}
Expand Down
20 changes: 0 additions & 20 deletions api/src/org/labkey/api/module/ModuleLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ public class ModuleLoader implements MemTrackerListener, ShutdownListener

private static Throwable _startupFailure = null;
private static boolean _newInstall = false;
private static TomcatVersion _tomcatVersion = null;
private static JavaVersion _javaVersion = null;

private static final String BANNER = """
Expand Down Expand Up @@ -535,8 +534,6 @@ private void doInit(Execution execution) throws ServletException

AppProps.getInstance().setContextPath(_servletContext.getContextPath());

setTomcatVersion();

File root = FileUtil.getAbsoluteCaseSensitiveFile(new File(_servletContext.getRealPath(""))).getParentFile();
FileLike labkeyRoot = new FileSystemLike.Builder(root).readwrite().noMemCheck().root();
_webappDir = labkeyRoot.resolveChild("labkeyWebapp");
Expand Down Expand Up @@ -1399,23 +1396,6 @@ public JavaVersion getJavaVersion()
return _javaVersion;
}

/**
* Sets the running Tomcat version, if servlet container is recognized and supported. Otherwise, ConfigurationException is thrown and server fails to start.
* <p>
* Warnings for deprecated Tomcat versions are handled in CoreWarningProvider.
*
* @throws ConfigurationException if Tomcat version is not recognized or supported
*/
private void setTomcatVersion()
{
_tomcatVersion = TomcatVersion.get();
}

public TomcatVersion getTomcatVersion()
{
return _tomcatVersion;
}

/**
* Initialize and update the Core module first. We want to change the core tables before we display pages, request
* login, check permissions, or initialize any of the other modules.
Expand Down
Loading