1616
1717package org .labkey .api .data ;
1818
19- import org .apache .logging .log4j .LogManager ;
2019import org .apache .logging .log4j .Logger ;
2120import org .labkey .api .cache .CacheManager ;
2221import org .labkey .api .data .dialect .SqlDialect ;
2322import org .labkey .api .util .FileUtil ;
2423import org .labkey .api .util .ShutdownListener ;
24+ import org .labkey .api .util .logging .LogHelper ;
2525
26- import java .io .File ;
2726import java .io .IOException ;
2827import java .io .RandomAccessFile ;
29- import java .lang .ref .Reference ;
30- import java .lang .ref .ReferenceQueue ;
31- import java .lang .ref .WeakReference ;
28+ import java .lang .ref .Cleaner ;
3229import java .util .Map ;
3330import java .util .TreeMap ;
3431import java .util .TreeSet ;
35- import java .util .concurrent .atomic .AtomicBoolean ;
3632
3733/**
3834 * User: Matthew
3935 * Date: May 4, 2006
4036 * Time: 7:27:50 PM
4137 */
42- public class TempTableTracker extends WeakReference < Object >
38+ public class TempTableTracker
4339{
44- private static final Logger _log = LogManager .getLogger (TempTableTracker .class );
40+ private static final Logger _log = LogHelper .getLogger (TempTableTracker .class , "Manages temp tables and their deletion" );
4541 private static final String LOGFILE = "CPAS_sqlTempTables.log" ;
4642 private static final Map <String , TempTableTracker > createdTableNames = new TreeMap <>();
47- private static final ReferenceQueue < Object > cleanupQueue = new ReferenceQueue <> ();
43+ private static final Cleaner cleaner = Cleaner . create ();
4844
4945 private static RandomAccessFile tempTableLog = null ;
5046
51- private final DbSchema schema ;
5247 private final String schemaName ;
5348 private final String tableName ;
5449 private final String qualifiedName ;
50+ private final Cleaner .Cleanable cleanable ;
51+ private final CleanupState state ;
5552
56- private boolean deleted = false ;
53+ private static class CleanupState implements Runnable
54+ {
55+ private final DbSchema schema ;
56+ private final String tableName ;
57+ private final String qualifiedName ;
58+ private final String schemaName ;
59+ private boolean deleted = false ;
5760
61+ private CleanupState (DbSchema schema , String tableName , String qualifiedName , String schemaName )
62+ {
63+ this .schema = schema ;
64+ this .tableName = tableName ;
65+ this .qualifiedName = qualifiedName ;
66+ this .schemaName = schemaName ;
67+ }
68+
69+ @ Override
70+ public void run ()
71+ {
72+ if (!deleted )
73+ {
74+ _log .debug ("Deleting table " + schema .getName () + "." + tableName );
75+ schema .dropTableIfExists (tableName );
76+
77+ deleted = true ;
78+ untrack (qualifiedName , schemaName , tableName );
79+ }
80+ }
81+ }
5882
5983 private TempTableTracker (DbSchema schema , String tableName , Object ref )
6084 {
61- super (ref , cleanupQueue );
62- this .schema = schema ;
6385 this .schemaName = schema .getName ();
6486 this .tableName = tableName ;
6587 this .qualifiedName = this .schemaName + "." + this .tableName ;
88+ this .state = new CleanupState (schema , tableName , qualifiedName , schemaName );
89+ cleanable = cleaner .register (ref , state );
6690 }
6791
6892
@@ -71,21 +95,19 @@ private TempTableTracker(String schemaName, String tableName, Object ref)
7195 this (DbSchema .get (schemaName ), tableName , ref ); // TODO: Treat as provisioned?
7296 }
7397
74- private static final Object initlock = new Object ();
98+ private static final Object LOCK = new Object ();
7599 private static boolean initialized = false ;
76100
77101 // make sure temp table tracker is initialized
78102 public static void init ()
79103 {
80- synchronized (initlock )
104+ synchronized (LOCK )
81105 {
82106 if (!initialized )
83107 {
84108 initialized = true ;
85109 synchronizeLog (true );
86110 purgeTempSchema ();
87- tempTableThread .setDaemon (true );
88- tempTableThread .start ();
89111 }
90112 }
91113 }
@@ -120,56 +142,22 @@ private static TempTableTracker track(TempTableTracker ttt)
120142 }
121143 }
122144
123-
124- private DbSchema getSchema ()
125- {
126- return schema ;
127- }
128-
129-
130145 public synchronized void delete ()
131146 {
132- if (deleted )
133- return ;
134-
135- sqlDelete ();
136-
137- deleted = true ;
138- untrack ();
139- }
140-
141-
142- private boolean sqlDelete ()
143- {
144- DbSchema schema = getSchema ();
145- _log .debug ("Deleting table " + schema .getName () + "." + tableName );
146- schema .dropTableIfExists (tableName );
147- return true ;
147+ cleanable .clean ();
148148 }
149149
150-
151- @ Override
152- protected void finalize () throws Throwable
153- {
154- if (!deleted )
155- _log .error ("finalizing undeleted TempTableTracker: " + qualifiedName );
156- super .finalize ();
157- }
158-
159-
160- private void untrack ()
150+ private static void untrack (String qualifiedName , String schemaName , String tableName )
161151 {
162152 _log .debug ("untrack(" + qualifiedName + ")" );
163153
164154 synchronized (createdTableNames )
165155 {
166- var ttt = createdTableNames .remove (qualifiedName );
156+ createdTableNames .remove (qualifiedName );
167157 appendToLog ("-" + schemaName + "\t " + tableName + "\n " );
168158
169159 if (createdTableNames .isEmpty () || System .currentTimeMillis () > lastSync + CacheManager .DAY )
170160 synchronizeLog (false );
171-
172- ttt .clear ();
173161 }
174162 }
175163
@@ -267,7 +255,7 @@ else if (s.charAt(0) == '-')
267255 tempTableLog .setLength (0 );
268256 for (TempTableTracker ttt : createdTableNames .values ())
269257 {
270- if (!ttt .deleted )
258+ if (!ttt .state . deleted )
271259 appendToLog ("+" + ttt .schemaName + "\t " + ttt .tableName + "\n " );
272260 }
273261 }
@@ -285,47 +273,12 @@ else if (s.charAt(0) == '-')
285273
286274 static final TempTableThread tempTableThread = new TempTableThread ();
287275
288- static class TempTableThread extends Thread implements ShutdownListener
276+ public static class TempTableThread implements ShutdownListener
289277 {
290- AtomicBoolean _shutdown = new AtomicBoolean (false );
291-
292- TempTableThread ()
293- {
294- super ("Temp table cleanup" );
295- setDaemon (true );
296- }
297-
298- @ Override
299- public void run ()
300- {
301- while (true )
302- {
303- try
304- {
305- Reference <?> r = _shutdown .get () ? cleanupQueue .poll () : cleanupQueue .remove ();
306- if (_shutdown .get () && r == null )
307- return ;
308- //noinspection RedundantCast
309- TempTableTracker t = (TempTableTracker )(Object )r ;
310- t .delete ();
311- }
312- catch (InterruptedException x )
313- {
314- _log .debug ("interrupted" );
315- }
316- catch (Throwable x )
317- {
318- _log .error ("unexpected error" , x );
319- }
320- }
321- }
322-
323-
324278 @ Override
325- public void shutdownPre ()
279+ public String getName ()
326280 {
327- _shutdown .set (true );
328- interrupt ();
281+ return "Temp table cleanup" ;
329282 }
330283
331284 @ Override
@@ -335,16 +288,10 @@ public void shutdownStarted()
335288 {
336289 for (TempTableTracker ttt : createdTableNames .values ())
337290 {
338- ttt .sqlDelete ();
339- ttt .deleted = true ;
291+ ttt .state .run ();
340292 }
341293 }
342294
343- try
344- {
345- join (5000 );
346- }
347- catch (InterruptedException ignored ) {}
348295 synchronizeLog (false );
349296 }
350297 }
0 commit comments