You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2005/06/06 12:18:12 UTC

svn commit: r180286 - in /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local: HandleMonitor.java LocalFileSystem.java

Author: tripod
Date: Mon Jun  6 03:18:08 2005
New Revision: 180286

URL: http://svn.apache.org/viewcvs?rev=180286&view=rev
Log:
- adding 'Handle monitor' to track open filehandles on windows boxes (see [JCR-128]

Added:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java   (with props)
Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java?rev=180286&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java Mon Jun  6 03:18:08 2005
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * 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.
+ */
+package org.apache.jackrabbit.core.fs.local;
+
+import org.apache.log4j.Logger;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.io.InputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * This Class implements a very simple open handle monitor for the local
+ * file system. This is usefull, if the list of open handles, referenced by
+ * an open FileInputStream() should be tracked. This can cause problems on
+ * windows filesystems where open files cannot be deleted.
+ */
+public class HandleMonitor {
+
+    /**
+     * The default logger
+     */
+    private static Logger log = Logger.getLogger(HandleMonitor.class);
+
+    /**
+     * the map of open handles (key=File, value=Handle)
+     */
+    private HashMap openHandles = new HashMap();
+
+    /**
+     * Opens a file and returns an InputStream
+     *
+     * @param file
+     * @return
+     * @throws FileNotFoundException
+     */
+    public InputStream open(File file) throws FileNotFoundException {
+        Handle handle = getHandle(file);
+        InputStream in = handle.open();
+        return in;
+    }
+
+    /**
+     * Checks, if the file is open
+     * @param file
+     * @return
+     */
+    public boolean isOpen(File file) {
+        return openHandles.containsKey(file);
+    }
+
+    /**
+     * Closes a file
+     * @param file
+     */
+    private void close(File file) {
+        openHandles.remove(file);
+    }
+
+    /**
+     * Returns the handle for a file.
+     * @param file
+     * @return
+     */
+    private Handle getHandle(File file) {
+        Handle handle = (Handle) openHandles.get(file);
+        if (handle == null) {
+            handle = new Handle(file);
+            openHandles.put(file, handle);
+        }
+        return handle;
+    }
+
+    /**
+     * Dumps the contents of this monitor
+     */
+    public void dump() {
+        log.info("Number of open files: " + openHandles.size());
+        Iterator iter = openHandles.keySet().iterator();
+        while (iter.hasNext()) {
+            File file = (File) iter.next();
+            Handle handle = (Handle) openHandles.get(file);
+            handle.dump();
+        }
+    }
+
+    /**
+     * Dumps the information for a file
+     * @param file
+     */
+    public void dump(File file) {
+        Handle handle = (Handle) openHandles.get(file);
+        if (handle != null) {
+            handle.dump(true);
+        }
+    }
+
+    /**
+     * Class representing all open handles to a file
+     */
+    private class Handle {
+
+        /**
+         * the file of this handle
+         */
+        private File file;
+
+        /**
+         * all open streams of this handle
+         */
+        private HashSet streams = new HashSet();
+
+        /**
+         * Creates a new handle for a file
+         * @param file
+         */
+        public Handle(File file) {
+            this.file = file;
+        }
+
+        /**
+         * opens a stream for this handle
+         * @return
+         * @throws FileNotFoundException
+         */
+        public InputStream open() throws FileNotFoundException {
+            Handle.MonitoredInputStream in = new Handle.MonitoredInputStream(file);
+            streams.add(in);
+            return in;
+        }
+
+        /**
+         * Closes a stream
+         * @param in
+         */
+        public void close(MonitoredInputStream in) {
+            streams.remove(in);
+            if (streams.isEmpty()) {
+                HandleMonitor.this.close(file);
+            }
+        }
+
+        /**
+         * Dumps this handle
+         */
+        public void dump() {
+            dump(false);
+        }
+
+        /**
+         * Dumps this handle
+         */
+        public void dump(boolean detailed) {
+            if (detailed) {
+                log.info("- " + file.getPath() + ", " + streams.size());
+                Iterator iter = streams.iterator();
+                while (iter.hasNext()) {
+                    Handle.MonitoredInputStream in = (Handle.MonitoredInputStream) iter.next();
+                    in.dump();
+                }
+            } else {
+                log.info("- " + file.getPath() + ", " + streams.size());
+            }
+        }
+
+        /**
+         * Delegating input stream that registers/unregisters itself from the
+         * handle.
+         */
+        private class MonitoredInputStream extends InputStream {
+
+            /**
+             * the underlying input stream
+             */
+            private final FileInputStream in;
+
+            /**
+             * throwable of the time, the stream was created
+             */
+            private final Throwable throwable;
+
+            /**
+             * Creates a new stream
+             * @param file
+             * @throws FileNotFoundException
+             */
+            public MonitoredInputStream(File file) throws FileNotFoundException {
+                in = new FileInputStream(file);
+                try {
+                    throw new Exception();
+                } catch (Exception e) {
+                    throwable = e;
+                }
+            }
+
+            /**
+             * dumps this stream
+             */
+            public void dump() {
+                log.info("- opened by : ", throwable);
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public int available() throws IOException {
+                return in.available();
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public void close() throws IOException {
+                in.close();
+                Handle.this.close(this);
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public synchronized void reset() throws IOException {
+                in.reset();
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public boolean markSupported() {
+                return in.markSupported();
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public synchronized void mark(int readlimit) {
+                in.mark(readlimit);
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public long skip(long n) throws IOException {
+                return in.skip(n);
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public int read(byte b[]) throws IOException {
+                return in.read(b);
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public int read(byte b[], int off, int len) throws IOException {
+                return in.read(b, off, len);
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            public int read() throws IOException {
+                return in.read();
+            }
+        }
+    }
+
+}

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/HandleMonitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java?rev=180286&r1=180285&r2=180286&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/fs/local/LocalFileSystem.java Mon Jun  6 03:18:08 2005
@@ -23,13 +23,13 @@
 
 import java.io.File;
 import java.io.FileFilter;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
+import java.io.FileInputStream;
 
 /**
  * A <code>LocalFileSystem</code> ...
@@ -40,6 +40,8 @@
 
     private File root;
 
+    private HandleMonitor monitor = null;
+
     /**
      * Default constructor
      */
@@ -127,6 +129,10 @@
                 throw new FileSystemException(msg);
             }
         }
+        log.info("LocaaFileSystem initialized on " + root.getPath());
+        if (monitor != null) {
+            log.info("LocalFileSystem using handle monitor");
+        }
     }
 
     /**
@@ -181,6 +187,11 @@
             FileUtil.delete(f);
         } catch (IOException ioe) {
             String msg = "failed to delete " + f.getPath();
+            if (monitor != null && monitor.isOpen(f)) {
+                log.error("Unable to delete. Still open streams");
+                monitor.dump(f);
+            }
+
             throw new FileSystemException(msg, ioe);
         }
     }
@@ -218,7 +229,11 @@
     public InputStream getInputStream(String filePath) throws FileSystemException {
         File f = new File(root, osPath(filePath));
         try {
-            return new FileInputStream(f);
+            if (monitor == null) {
+                return new FileInputStream(f);
+            } else {
+                return monitor.open(f);
+            }
         } catch (FileNotFoundException fnfe) {
             String msg = f.getPath() + " does not denote an existing file";
             log.debug(msg);
@@ -415,5 +430,37 @@
             throw new FileSystemException(msg, ioe);
         }
 */
+    }
+
+    /**
+     * Enables the usage of the handle monitor.
+     *
+     * @param enable
+     */
+    public void setEnableHandleMonitor(String enable) {
+        setEnableHandleMonitor(Boolean.valueOf(enable).booleanValue());
+    }
+
+
+    /**
+     * Returns if the handle monitor is enabled
+     */
+    public String getEnableHandleMonitor() {
+        return monitor == null ? "false" : "true";
+    }
+
+
+    /**
+     * Enables the usage of the handle monitor.
+     *
+     * @param enable
+     */
+    public void setEnableHandleMonitor(boolean enable) {
+        if (enable && monitor == null) {
+            monitor = new HandleMonitor();
+        }
+        if (!enable && monitor != null) {
+            monitor = null;
+        }
     }
 }