diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java')
-rw-r--r-- | bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java index 3edcfd956..b903583e9 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/MRUBundleFileList.java @@ -12,6 +12,7 @@ package org.eclipse.osgi.baseadaptor.bundlefile; import java.io.IOException; +import org.eclipse.osgi.framework.eventmgr.*; /** * A simple/quick/small implementation of an MRU (Most Recently Used) list to keep @@ -20,7 +21,7 @@ import java.io.IOException; * file limit. * @since 3.2 */ -public class MRUBundleFileList { +public class MRUBundleFileList implements EventDispatcher { private static final String PROP_FILE_LIMIT = "osgi.bundlefile.limit"; //$NON-NLS-1$ private static final int MIN = 10; // list of open bundle files @@ -33,6 +34,8 @@ public class MRUBundleFileList { private int fileLimit = 0; // value < MIN will disable MRU // the current number of open bundle files private int numOpen = 0; + private EventManager bundleFileCloserManager; + private EventListeners bundleFileCloser; public MRUBundleFileList() { try { @@ -54,6 +57,9 @@ public class MRUBundleFileList { this.fileLimit = initFileLimit; this.bundleFileList = new BundleFile[initFileLimit]; this.useStampList = new long[initFileLimit]; + this.bundleFileCloserManager = new EventManager("Bundle File Closer"); //$NON-NLS-1$ + this.bundleFileCloser = new EventListeners(); + this.bundleFileCloser.addListener(this, this); } } @@ -67,6 +73,7 @@ public class MRUBundleFileList { public void add(BundleFile bundleFile) throws IOException { if (fileLimit < MIN) return; // MRU is disabled + BundleFile toRemove = null; synchronized (bundleFileList) { int index = 0; // default to the first slot if (numOpen < fileLimit) { @@ -85,9 +92,8 @@ public class MRUBundleFileList { for (int i = 1; i < fileLimit; i++) if (useStampList[i] < useStampList[index]) index = i; - BundleFile toRemove = bundleFileList[index]; + toRemove = bundleFileList[index]; remove(toRemove); - toRemove.close(); } // found an index to place to bundleFile to be opened bundleFileList[index] = bundleFile; @@ -95,6 +101,9 @@ public class MRUBundleFileList { incUseStamp(index); numOpen++; } + // must not close the toRemove bundle file while holding the lock of another bundle file (bug 161976) + // This queue the bundle file for close asynchronously. + closeBundleFile(toRemove); } /** @@ -107,7 +116,8 @@ public class MRUBundleFileList { return false; // MRU is disabled synchronized (bundleFileList) { int index = bundleFile.getMruIndex(); - if ((index >= 0 || index < fileLimit) && bundleFileList[index] == bundleFile) { + if ((index >= 0 && index < fileLimit) && bundleFileList[index] == bundleFile) { + bundleFile.setMruIndex(-1); bundleFileList[index] = null; useStampList[index] = -1; numOpen--; @@ -126,7 +136,7 @@ public class MRUBundleFileList { return; // MRU is disabled synchronized (bundleFileList) { int index = bundleFile.getMruIndex(); - if ((index >= 0 || index < fileLimit) && bundleFileList[index] == bundleFile) + if ((index >= 0 && index < fileLimit) && bundleFileList[index] == bundleFile) incUseStamp(index); } } @@ -140,4 +150,23 @@ public class MRUBundleFileList { } useStampList[index] = ++curUseStamp; } + + public final void dispatchEvent(Object eventListener, Object listenerObject, int eventAction, Object eventObject) { + try { + ((BundleFile) eventObject).close(); + } catch (IOException e) { + // TODO should log ?? + } + } + + private void closeBundleFile(BundleFile toRemove) { + if (toRemove == null) + return; + /* queue to hold set of listeners */ + ListenerQueue queue = new ListenerQueue(bundleFileCloserManager); + /* add bundle file closer to the queue */ + queue.queueListeners(bundleFileCloser, this); + /* dispatch event to set of listeners */ + queue.dispatchEventAsynchronous(0, toRemove); + } } |