[jboss-cvs] JBossAS SVN: r73688 - projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon May 26 13:33:40 EDT 2008
Author: mstruk
Date: 2008-05-26 13:33:40 -0400 (Mon, 26 May 2008)
New Revision: 73688
Added:
projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java
Modified:
projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
Log:
Async archive file release optimization - 5 seconds inactivity period triggers release
Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java 2008-05-26 17:33:40 UTC (rev 73688)
@@ -0,0 +1,149 @@
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.logging.Logger;
+
+import java.util.Iterator;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Monitoring object that closes ZipFiles when they haven't been used for a while
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipFileLockReaper
+{
+ /** Logger */
+ private static final Logger log = Logger.getLogger(ZipFileLockReaper.class);
+
+ /**
+ * Time after which unused ZipFiles can be closed. This shouldn't be a large number
+ * to ensure smooth releasing of file locks
+ */
+ private static final int PERIOD = 5000;
+
+ /** Timer thread period */
+ private static final int TIMER_PERIOD = 1000;
+
+ /** If timer finds out there are no open ZipFiles for a while it shuts down until some are (re)opened */
+ private static final int TIMER_UNUSED_PERIOD = 30000;
+
+ /** There is only one instance that serves all ZipFileWrappers */
+ private static ZipFileLockReaper singleton;
+
+ /** A list of monitored ZipFileWrappers */
+ private ConcurrentLinkedQueue monitored = new ConcurrentLinkedQueue();
+
+ /** The number of monitored ZipFileWrappers */
+ private int monitoredCount = 0;
+
+ /** Timer used for actual reaping - async closure of ZipFiles */
+ private Timer timer;
+
+ /** Timestamp of last unregister() call */
+ private long lastUsed;
+
+
+ /**
+ * Private constructor - to force retrieval through {@link #getInstance()}
+ */
+ private ZipFileLockReaper()
+ {
+
+ }
+
+ /** Factory method to be used to retrieve reference to ZipFileLockReaper */
+ public synchronized static ZipFileLockReaper getInstance()
+ {
+ if (singleton == null)
+ singleton = new ZipFileLockReaper();
+
+ return singleton;
+ }
+
+
+ /** Register a ZipFileWrapper instance with this reaper */
+ public synchronized void register(ZipFileWrapper w)
+ {
+ monitored.add(w);
+ monitoredCount++;
+ if (timer == null)
+ {
+ timer = new Timer("ZipFile Lock Reaper", true);
+ timer.schedule(new ReaperTimerTask(), TIMER_PERIOD, TIMER_PERIOD);
+ }
+ log.debug("Registered: " + w);
+ }
+
+ /** Unregister a ZipFileWrapper instance from this reaper */
+ public synchronized void unregister(ZipFileWrapper w)
+ {
+ monitored.remove(w);
+ monitoredCount--;
+ lastUsed = System.currentTimeMillis();
+ log.debug("Unregistered: " + w);
+ }
+
+
+
+ /** Timer task that does the actual reaping */
+ class ReaperTimerTask extends TimerTask
+ {
+ public void run()
+ {
+ log.debug("Timer called");
+
+ long now = System.currentTimeMillis();
+ synchronized (ZipFileLockReaper.this)
+ {
+ if (monitoredCount == 0)
+ {
+ if (now - lastUsed > TIMER_UNUSED_PERIOD)
+ {
+ timer.cancel();
+ timer = null;
+ log.debug("Cancelled the timer");
+ }
+ return;
+ }
+ }
+
+ Iterator it = monitored.iterator();
+ while (it.hasNext())
+ {
+ ZipFileWrapper w = (ZipFileWrapper) it.next();
+
+ // stream leak debug
+ /*
+ Iterator<ZipEntryInputStream> sit = w.streams.iterator();
+ while (sit.hasNext())
+ {
+ ZipEntryInputStream eis = sit.next();
+ if (!eis.isClosed())
+ {
+ System.out.println("Stream not closed: " + eis.debugCount + " - " + eis);
+ }
+ }
+ */
+
+ if (w.getReferenceCount() <= 0 && now - w.getLastUsed() > PERIOD)
+ {
+ try
+ {
+ w.closeZipFile();
+ log.debug("Asynchronously closed an unused ZipFile: " + w);
+ }
+ catch(Exception ex)
+ {
+ // ignore the exception
+ log.debug("Failed to close ZipFile: ", ex);
+ }
+ }
+ }
+ }
+ }
+
+}
Modified: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java 2008-05-26 17:17:42 UTC (rev 73687)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java 2008-05-26 17:33:40 UTC (rev 73688)
@@ -30,6 +30,10 @@
private int refCount = 0;
+ // used for debugging stream leaks
+ //ConcurrentLinkedQueue<ZipEntryInputStream> streams = new ConcurrentLinkedQueue<ZipEntryInputStream>();
+
+
public ZipFileWrapper(File archive)
{
file = archive;
@@ -58,21 +62,35 @@
return file.isFile();
}
+ long getLastUsed()
+ {
+ return lastUsed;
+ }
+
+ int getReferenceCount()
+ {
+ return refCount;
+ }
+
private ZipFile ensureZipFile() throws IOException
{
if (zipFile == null)
+ {
zipFile = new ZipFile(file);
+ ZipFileLockReaper.getInstance().register(this);
+ }
return zipFile;
}
- private void closeZipFile() throws IOException
+ synchronized void closeZipFile() throws IOException
{
- if (zipFile != null)
+ if (zipFile != null && refCount <= 0)
{
ZipFile zf = zipFile;
zipFile = null;
zf.close();
+ ZipFileLockReaper.getInstance().unregister(this);
}
}
@@ -81,6 +99,10 @@
ensureZipFile();
InputStream is = zipFile.getInputStream(ent);
ZipEntryInputStream zis = new ZipEntryInputStream(this, is);
+
+ // debugging code
+ //streams.add(zis);
+
refCount++;
lastUsed = System.currentTimeMillis();
return zis;
@@ -95,7 +117,8 @@
try
{
lastUsed = System.currentTimeMillis();
- closeZipFile();
+ // let the reaper do its job
+ //closeZipFile();
}
catch(Exception ex)
{
@@ -122,4 +145,9 @@
log.warn("Failed to release file: " + file);
}
}
+
+ public String toString()
+ {
+ return super.toString() + " - " + file.getAbsolutePath();
+ }
}
More information about the jboss-cvs-commits
mailing list