You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by im...@apache.org on 2005/11/06 19:49:17 UTC

svn commit: r331133 - /jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java

Author: imario
Date: Sun Nov  6 10:48:29 2005
New Revision: 331133

URL: http://svn.apache.org/viewcvs?rev=331133&view=rev
Log:
try to avoid locking as pointed out by Faron Dutton

Modified:
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java?rev=331133&r1=331132&r2=331133&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java Sun Nov  6 10:48:29 2005
@@ -1,20 +1,28 @@
 /*
  * Copyright 2002-2005 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
  */
 package org.apache.commons.vfs.cache;
 
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.vfs.FileName;
@@ -24,244 +32,268 @@
 import org.apache.commons.vfs.impl.DefaultFileSystemManager;
 import org.apache.commons.vfs.util.Messages;
 
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-
 /**
- * This implementation caches every file as long as it is strongly reachable by the java vm.
- * As soon as the vm needs memory - every softly reachable file will be discarded.
- *
+ * This implementation caches every file as long as it is strongly reachable by
+ * the java vm. As soon as the vm needs memory - every softly reachable file
+ * will be discarded.
+ * 
  * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
- * @version $Revision$ $Date$
+ * @version $Revision$ $Date: 2005-09-30 09:02:41 +0200 (Fr, 30 Sep
+ *          2005) $
  * @see SoftReference
  */
 public class SoftRefFilesCache extends AbstractFilesCache
 {
-    /**
-     * The logger to use.
-     */
-    private Log log = LogFactory.getLog(SoftRefFilesCache.class);
-
-    private final Map filesystemCache = new HashMap();
-    private final Map refReverseMap = new HashMap(100);
-    private final ReferenceQueue refqueue = new ReferenceQueue();
-
-    private SoftRefReleaseThread softRefReleaseThread = null;
-
-    /**
-     * This thread will listen on the ReferenceQueue and remove the entry in the
-     * filescache as soon as the vm removes the reference
-     */
-    private class SoftRefReleaseThread extends Thread
-    {
-        private boolean requestEnd = false;
-
-        private SoftRefReleaseThread()
-        {
-            setName(SoftRefReleaseThread.class.getName());
-            setDaemon(true);
-        }
-
-        public void run()
-        {
-            loop: while (!requestEnd && !Thread.currentThread().isInterrupted())
-            {
-                try
-                {
-                    Reference ref = refqueue.remove(1000);
-                    if (ref == null)
-                    {
-                        continue;
-                    }
-
-                    synchronized (SoftRefFilesCache.this)
-                    {
-                        FileSystemAndNameKey key = (FileSystemAndNameKey) refReverseMap.get(ref);
-
-                        if (key != null)
-                        {
-                            removeFile(key);
-                        }
-                    }
-                }
-                catch (InterruptedException e)
-                {
-                    if (!requestEnd)
-                    {
-                        VfsLog.warn(getLogger(), log, Messages.getString("vfs.impl/SoftRefReleaseThread-interrupt.info"));
-                    }
-                    break loop;
-                }
-            }
-        }
-    }
-
-    public SoftRefFilesCache()
-    {
-    }
-
-    private void startThread()
-    {
-        if (softRefReleaseThread != null)
-        {
-            throw new IllegalStateException(Messages.getString("vfs.impl/SoftRefReleaseThread-already-running.warn"));
-        }
-
-        softRefReleaseThread = new SoftRefReleaseThread();
-        softRefReleaseThread.start();
-    }
-
-    private void endThread()
-    {
-        if (softRefReleaseThread != null)
-        {
-            softRefReleaseThread.requestEnd = true;
-            softRefReleaseThread.interrupt();
-            softRefReleaseThread = null;
-        }
-    }
-
-    public void putFile(final FileObject file)
-    {
-        if (log.isDebugEnabled())
-        {
-            log.debug("putFile: " + file.getName());
-        }
-        synchronized (this)
-        {
-            Map files = getOrCreateFilesystemCache(file.getFileSystem());
-
-            Reference ref = new SoftReference(file, refqueue);
-            FileSystemAndNameKey key = new FileSystemAndNameKey(file.getFileSystem(), file.getName());
-            files.put(file.getName(), ref);
-            refReverseMap.put(ref, key);
-        }
-    }
-
-    public FileObject getFile(final FileSystem filesystem, final FileName name)
-    {
-        synchronized (this)
-        {
-            Map files = getOrCreateFilesystemCache(filesystem);
-
-            SoftReference ref = (SoftReference) files.get(name);
-            if (ref == null)
-            {
-                return null;
-            }
-
-            FileObject fo = (FileObject) ref.get();
-            if (fo == null)
-            {
-                removeFile(filesystem, name);
-            }
-            return fo;
-        }
-    }
-
-    public void clear(FileSystem filesystem)
-    {
-        synchronized (this)
-        {
-            Map files = getOrCreateFilesystemCache(filesystem);
-
-            Iterator iterKeys = refReverseMap.values().iterator();
-            while (iterKeys.hasNext())
-            {
-                FileSystemAndNameKey key = (FileSystemAndNameKey) iterKeys.next();
-                if (key.getFileSystem() == filesystem)
-                {
-                    iterKeys.remove();
-                    files.remove(key.getFileName());
-                }
-            }
-
-            if (files.size() < 1)
-            {
-                filesystemClose(filesystem);
-            }
-        }
-    }
-
-    private void filesystemClose(FileSystem filesystem)
-    {
-        if (log.isDebugEnabled())
-        {
-            log.debug("close fs: " + filesystem.getRootName());
-        }
-        filesystemCache.remove(filesystem);
-        if (filesystemCache.size() < 1)
-        {
-            endThread();
-        }
-        ((DefaultFileSystemManager) getContext().getFileSystemManager()).closeFileSystem(filesystem);
-    }
-
-    public void close()
-    {
-        super.close();
-
-        synchronized (this)
-        {
-            endThread();
-
-            // files.clear();
-            filesystemCache.clear();
-            refReverseMap.clear();
-        }
-    }
-
-    public void removeFile(FileSystem filesystem, FileName name)
-    {
-        removeFile(new FileSystemAndNameKey(filesystem, name));
-    }
-
-    public void touchFile(FileObject file)
-    {
-    }
-
-    private void removeFile(final FileSystemAndNameKey key)
-    {
-        if (log.isDebugEnabled())
-        {
-            log.debug("removeFile: " + key.getFileName());
-        }
-        synchronized (this)
-        {
-            Map files = getOrCreateFilesystemCache(key.getFileSystem());
-
-            Object ref = files.remove(key.getFileName());
-            if (ref != null)
-            {
-                refReverseMap.remove(ref);
-            }
-
-            if (files.size() < 1)
-            {
-                filesystemClose(key.getFileSystem());
-            }
-        }
-    }
-
-    protected Map getOrCreateFilesystemCache(final FileSystem filesystem)
-    {
-        if (filesystemCache.size() < 1)
-        {
-            startThread();
-        }
-
-        Map files = (Map) filesystemCache.get(filesystem);
-        if (files == null)
-        {
-            files = new TreeMap();
-            filesystemCache.put(filesystem, files);
-        }
-
-        return files;
-    }
+	/**
+	 * The logger to use.
+	 */
+	private Log log = LogFactory.getLog(SoftRefFilesCache.class);
+
+	private final Map filesystemCache = new HashMap();
+	private final Map refReverseMap = new HashMap(100);
+	private final ReferenceQueue refqueue = new ReferenceQueue();
+
+	private SoftRefReleaseThread softRefReleaseThread = null;
+
+	/**
+	 * This thread will listen on the ReferenceQueue and remove the entry in the
+	 * filescache as soon as the vm removes the reference
+	 */
+	private class SoftRefReleaseThread extends Thread
+	{
+		private boolean requestEnd = false;
+
+		private SoftRefReleaseThread()
+		{
+			setName(SoftRefReleaseThread.class.getName());
+			setDaemon(true);
+		}
+
+		public void run()
+		{
+			loop: while (!requestEnd && !Thread.currentThread().isInterrupted())
+			{
+				try
+				{
+					Reference ref = refqueue.remove(1000);
+					if (ref == null)
+					{
+						continue;
+					}
+
+					FileSystem fsToRemove = null;
+
+					FileSystemAndNameKey key = (FileSystemAndNameKey) refReverseMap
+							.get(ref);
+
+					if (key != null)
+					{
+						if (removeFile(key))
+						{
+							fsToRemove = key.getFileSystem();
+						}
+					}
+
+					if (fsToRemove != null)
+					{
+						filesystemClose(fsToRemove);
+					}
+				}
+				catch (InterruptedException e)
+				{
+					if (!requestEnd)
+					{
+						VfsLog
+								.warn(
+										getLogger(),
+										log,
+										Messages
+												.getString("vfs.impl/SoftRefReleaseThread-interrupt.info"));
+					}
+					break loop;
+				}
+			}
+		}
+	}
+
+	public SoftRefFilesCache()
+	{
+	}
+
+	private void startThread()
+	{
+		if (softRefReleaseThread != null)
+		{
+			throw new IllegalStateException(
+					Messages
+							.getString("vfs.impl/SoftRefReleaseThread-already-running.warn"));
+		}
+
+		softRefReleaseThread = new SoftRefReleaseThread();
+		softRefReleaseThread.start();
+	}
+
+	private void endThread()
+	{
+		if (softRefReleaseThread != null)
+		{
+			softRefReleaseThread.requestEnd = true;
+			softRefReleaseThread.interrupt();
+			softRefReleaseThread = null;
+		}
+	}
+
+	public void putFile(final FileObject file)
+	{
+		if (log.isDebugEnabled())
+		{
+			log.debug("putFile: " + file.getName());
+		}
+
+		Map files = getOrCreateFilesystemCache(file.getFileSystem());
+
+		Reference ref = new SoftReference(file, refqueue);
+		FileSystemAndNameKey key = new FileSystemAndNameKey(file
+				.getFileSystem(), file.getName());
+
+		synchronized (files)
+		{
+			files.put(file.getName(), ref);
+			refReverseMap.put(ref, key);
+		}
+	}
+
+	public FileObject getFile(final FileSystem filesystem, final FileName name)
+	{
+		Map files = getOrCreateFilesystemCache(filesystem);
+
+		synchronized (files)
+		{
+			SoftReference ref = (SoftReference) files.get(name);
+			if (ref == null)
+			{
+				return null;
+			}
+
+			FileObject fo = (FileObject) ref.get();
+			if (fo == null)
+			{
+				removeFile(filesystem, name);
+			}
+			return fo;
+		}
+	}
+
+	public void clear(FileSystem filesystem)
+	{
+		Map files = getOrCreateFilesystemCache(filesystem);
+
+		synchronized (files)
+		{
+			Iterator iterKeys = refReverseMap.values().iterator();
+			while (iterKeys.hasNext())
+			{
+				FileSystemAndNameKey key = (FileSystemAndNameKey) iterKeys
+						.next();
+				if (key.getFileSystem() == filesystem)
+				{
+					iterKeys.remove();
+					files.remove(key.getFileName());
+				}
+			}
+		}
+
+		if (files.size() < 1)
+		{
+			filesystemClose(filesystem);
+		}
+	}
+
+	private void filesystemClose(FileSystem filesystem)
+	{
+		if (log.isDebugEnabled())
+		{
+			log.debug("close fs: " + filesystem.getRootName());
+		}
+		synchronized (filesystemCache)
+		{
+			filesystemCache.remove(filesystem);
+			if (filesystemCache.size() < 1)
+			{
+				endThread();
+			}
+		}
+		((DefaultFileSystemManager) getContext().getFileSystemManager())
+				.closeFileSystem(filesystem);
+	}
+
+	public void close()
+	{
+		super.close();
+
+		synchronized (this)
+		{
+			endThread();
+
+			// files.clear();
+			synchronized (filesystemCache)
+			{
+				filesystemCache.clear();
+			}
+			refReverseMap.clear();
+		}
+	}
+
+	public void removeFile(FileSystem filesystem, FileName name)
+	{
+		if (removeFile(new FileSystemAndNameKey(filesystem, name)))
+		{
+			filesystemClose(filesystem);
+		}
+	}
+
+	public void touchFile(FileObject file)
+	{
+	}
+
+	private boolean removeFile(final FileSystemAndNameKey key)
+	{
+		if (log.isDebugEnabled())
+		{
+			log.debug("removeFile: " + key.getFileName());
+		}
+
+		Map files = getOrCreateFilesystemCache(key.getFileSystem());
+
+		synchronized (files)
+		{
+			Object ref = files.remove(key.getFileName());
+			if (ref != null)
+			{
+				refReverseMap.remove(ref);
+			}
+
+			return files.size() < 1;
+		}
+	}
+
+	protected Map getOrCreateFilesystemCache(final FileSystem filesystem)
+	{
+		synchronized (filesystemCache)
+		{
+			if (filesystemCache.size() < 1)
+			{
+				startThread();
+			}
+
+			Map files = (Map) filesystemCache.get(filesystem);
+			if (files == null)
+			{
+				files = new TreeMap();
+				filesystemCache.put(filesystem, files);
+			}
+
+			return files;
+		}
+	}
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org