zipfs problems
Joel Uckelman
uckelman at nomic.net
Tue Oct 20 13:07:40 PDT 2009
Thus spake Joel Uckelman:
> Thus spake Alan Bateman:
> >
> > You are right and there are concurrency issues here. Also all returned
> > closeables should be wrapped so that close method removes them from the
> > set. Rajendra, do you have cycles to fix this?
>
> Actually, I've already done it for closeableObjects. The only issue I'm
> wondering aobut is whether to use Collections.synchronizedSet() or to
> build a Set wrapper for a ConcurrentHashMap.
>
Here's a patch for this issue.
-------------- next part --------------
# HG changeset patch
# User uckelman at adsl-208-39.dsl.uva.nl
# Date 1256066426 -7200
# Node ID 707295cce2384eb8083246a7910b862f997bfa8d
# Parent 9b426af16c0dae4b85a53e9766c6fe92345a31a5
* Renamed closeableObjects to closeables (Objects is redundant).
* closeables is now a synchronized Set to prevent concurrent modification
* InputStreams and SeekableByteChannels now register themselves with
ZipFileSystem on creation and unregister themselves on closure.
diff --git a/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java b/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java
--- a/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java
+++ b/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java
@@ -31,6 +31,7 @@
package com.sun.nio.zipfs;
import java.io.File;
+import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -727,6 +728,73 @@
return pathToZip;
}
+ /**
+ * An {@link InputStream} which registers itself with the
+ * {@link ZipFileSystem} on creation and unregisters itself on
+ * closure.
+ */
+ private class ZipFilePathInputStream extends FilterInputStream {
+ public ZipFilePathInputStream(InputStream in) {
+ super(in);
+ fileSystem.registerCloseable(this);
+ }
+
+ @Override
+ public void close() throws IOException {
+ in.close();
+ fileSystem.unregisterCloseable(this);
+ }
+ }
+
+ /**
+ * A {@link SeekableByteChannel} which registers itself with the
+ * {@link ZipFileSystem} on creation and unregisters itself on
+ * closure.
+ */
+ private class ZipFilePathChannel implements SeekableByteChannel {
+ private final SeekableByteChannel ch;
+
+ public ZipFilePathChannel(SeekableByteChannel ch) {
+ this.ch = ch;
+ fileSystem.registerCloseable(this);
+ }
+
+ public long position() throws IOException {
+ return ch.position();
+ }
+
+ public SeekableByteChannel position(long newPos) throws IOException {
+ ch.position(newPos);
+ return this;
+ }
+
+ public int read(ByteBuffer dst) throws IOException {
+ return ch.read(dst);
+ }
+
+ public long size() throws IOException {
+ return ch.size();
+ }
+
+ public SeekableByteChannel truncate(long size) throws IOException {
+ ch.truncate(size);
+ return this;
+ }
+
+ public int write(ByteBuffer src) throws IOException {
+ return ch.write(src);
+ }
+
+ public boolean isOpen() {
+ return ch.isOpen();
+ }
+
+ public void close() throws IOException {
+ ch.close();
+ fileSystem.unregisterCloseable(this);
+ }
+ }
+
@Override
public InputStream newInputStream(OpenOption... options)
throws IOException {
@@ -751,9 +819,8 @@
zfile.close();
throw new IOException("entry not found" + entryStr);
}
- InputStream is = zfile.getInputStream(entry);
- fileSystem.addCloseableObjects(is);
- return is;
+
+ return new ZipFilePathInputStream(zfile.getInputStream(entry));
}
} finally {
end();
@@ -1009,9 +1076,10 @@
InputStream in = zfile.getInputStream(entry);
Path pathtoZip = Paths.get(ZipUtils.readFileInZip(in));
zfile.close();
- SeekableByteChannel sbc = FileChannel.open(pathtoZip, options);
- fileSystem.addCloseableObjects(sbc);
- return sbc;
+
+ return new ZipFilePathChannel(
+ FileChannel.open(pathtoZip, options)
+ );
}
} finally {
end();
diff --git a/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java b/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java
--- a/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java
+++ b/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFileSystem.java
@@ -51,7 +51,9 @@
private final String defaultdir;
private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
private boolean open = true;
- private Set<Closeable> closeableObjects = new HashSet<Closeable>();
+
+ private final Set<Closeable> closeables =
+ Collections.synchronizedSet(new HashSet<Closeable>());
ZipFileSystem(ZipFileSystemProvider provider,
FileRef fref) {
@@ -117,7 +119,7 @@
private void implClose(URI root) throws IOException {
ZipUtils.remove(root); // remove cached filesystem
provider.removeFileSystem(root);
- Iterator<Closeable> itr = closeableObjects.iterator();
+ Iterator<Closeable> itr = closeables.iterator();
while (itr.hasNext()) {
try {
itr.next().close();
@@ -128,8 +130,12 @@
}
}
- boolean addCloseableObjects(Closeable obj) {
- return closeableObjects.add(obj);
+ boolean registerCloseable(Closeable c) {
+ return closeables.add(c);
+ }
+
+ boolean unregisterCloseable(Closeable c) {
+ return closeables.remove(c);
}
@Override
# HG changeset patch
# User uckelman at adsl-208-39.dsl.uva.nl
# Date 1256067699 -7200
# Node ID 716fe8ce64d09f69265c46466f5d53eca296a35a
# Parent 707295cce2384eb8083246a7910b862f997bfa8d
Added missing import.
diff --git a/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java b/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java
--- a/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java
+++ b/src/share/demo/nio/ZipFileSystem/com/sun/nio/zipfs/ZipFilePath.java
@@ -35,6 +35,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.*;
import java.nio.file.DirectoryStream.Filter;
More information about the nio-dev
mailing list