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