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;
+ }
}
}