Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > HELP: java1.4.2 on windows, FileChannel.Close

Reply
Thread Tools

HELP: java1.4.2 on windows, FileChannel.Close

 
 
Andrew Rollings
Guest
Posts: n/a
 
      01-31-2004
Hi...
I'm having a few problems with the close method of the FileChannel class in
Sun java 1.4.2 (latest as of this date) on Windows.
The code I've written seems to perform as expected on both MacOsX and linux,
so I'm wondering if anyone has come across similar circumstances, and has
found a workaround.

Or alternatively, just tell me what I'm doing that's dumb.

I have a class that maintains a TreeMap of FileChannels. At a certain point
in the class execution, I iterate through the map, and close out all of the
channels, and then attempt to delete the underlying file.
The code to this this is as follows:


-- begin excerpt
Iterator iter = m_FileChannelMap.keySet().iterator();
java.util.Vector keysToRemove = new java.util.Vector();
while ( iter.hasNext() )
{
Long lKey = ( Long ) iter.next();
if (lKey.longValue() < 0)
{
// get the channel and close it
FileChannel fc = (FileChannel)m_FileChannelMap.get(lKey);
fc.truncate(0);
fc.force(true);
fc.close();

// okay - file channel should be closed... we can delete the
// file it represents...
String strFilename = m_strFileroot +
this.getSegmentName(lKey.longValue());
if (!strFilename.endsWith(".T")) throw new IOException("Invalid
segment");
java.io.File fSegment = new File(strFilename);
if (false == fSegment.delete())
{
throw new IOException("Cannot close .T segment:" +
strFilename );
}
}
}
-- end excerpt

The problem is, that the IOException is *always* thrown. It seems that
FileChannel.close() does not immediately close the channel. I'm wondering if
this is anything to do with the fact that I'm maintaining a reference to the
FileChannel object in the TreeMap, but I don't see why that should be the
case. Anyway, this code works perfectly on Mac and Linux, but appears to
barf out on Windows.

Can anyone tell me what's wrong with the code? Failing that can anyone
suggest an alternate method that will work?
(And as an aside, is it safe to remove an item from the map while I'm
iterating through it? I don't currently do that, but I may want to at some
point.)

Thanks for reading.

Andrew


 
Reply With Quote
 
 
 
 
John C. Bollinger
Guest
Posts: n/a
 
      02-02-2004
Andrew Rollings wrote:

> Hi...
> I'm having a few problems with the close method of the FileChannel class in
> Sun java 1.4.2 (latest as of this date) on Windows.
> The code I've written seems to perform as expected on both MacOsX and linux,
> so I'm wondering if anyone has come across similar circumstances, and has
> found a workaround.
>
> Or alternatively, just tell me what I'm doing that's dumb.
>
> I have a class that maintains a TreeMap of FileChannels. At a certain point


That's dumb unless it's important that the channels remain always in
order by whatever key you use, including if you need to use the methods
specific to the SortedSet interface. In any other circumstance a
HashMap is a better choice. That isn't relevant to your problem, however.

> in the class execution, I iterate through the map, and close out all of the
> channels, and then attempt to delete the underlying file.
> The code to this this is as follows:
>
>
> -- begin excerpt
> Iterator iter = m_FileChannelMap.keySet().iterator();


I'd iterate over the entry set, myself, since you are going to retrive
the value for each key anyway. That's not causing your problem either
though.

> java.util.Vector keysToRemove = new java.util.Vector();


You don't appear to use this Vector.

> while ( iter.hasNext() )
> {
> Long lKey = ( Long ) iter.next();
> if (lKey.longValue() < 0)
> {


That's a bit odd. You identify the entries to close by their keys? I
thought you were closing them all. Did you somehow arrange that the
keys you were interested in would all be negative, or did you rekey the
channels? (The latter would be quite inefficient, and more so for a
TreeMap than for a HashMap.)

> // get the channel and close it
> FileChannel fc = (FileChannel)m_FileChannelMap.get(lKey);
> fc.truncate(0);
> fc.force(true);
> fc.close();
>
> // okay - file channel should be closed... we can delete the
> // file it represents...
> String strFilename = m_strFileroot +
> this.getSegmentName(lKey.longValue());
> if (!strFilename.endsWith(".T")) throw new IOException("Invalid
> segment");
> java.io.File fSegment = new File(strFilename);
> if (false == fSegment.delete())
> {
> throw new IOException("Cannot close .T segment:" +
> strFilename );
> }
> }
> }
> -- end excerpt
>
> The problem is, that the IOException is *always* thrown. It seems that
> FileChannel.close() does not immediately close the channel.


From the API docs of FileChannel's superclass,
AbstractInterruptibleChannel: "This class encapsulates the low-level
machinery required to implement the asynchronous closing and
interruption of channels." It would appear, then, that asynchronous
closing is a design feature of the class.

> I'm wondering if
> this is anything to do with the fact that I'm maintaining a reference to the
> FileChannel object in the TreeMap, but I don't see why that should be the
> case.


No, there is no reason why holding a reference in any particular place
would affect the behavior of an object in any way. Affect the behavior
of the GC, yes, but not of the object.

> Anyway, this code works perfectly on Mac and Linux, but appears to
> barf out on Windows.


I'd say that the code is just plain buggy, even if so far the problem
has only manifested on Windows. Since you are already truncating the
files to zero length, perhaps it would be sufficient to flag them for
deletion on JVM exit instead of deleting them immediately (via
File.deleteOnExit()). If you must affirmatively delete them then you
must be prepared to handle the possibility that they are sill open when
you attempt to do so. One way of handling that would be to catch the
exception and try again after a delay.

> Can anyone tell me what's wrong with the code? Failing that can anyone
> suggest an alternate method that will work?


See above.

> (And as an aside, is it safe to remove an item from the map while I'm
> iterating through it? I don't currently do that, but I may want to at some
> point.)


Only if you do so via the iterator itself; otherwise (for TreeMap) you
will get ConcurrentModificationException from you iterator after the
removal. For Generic Maps behavior of the iterator subsequent to
modification of the underlying Map is undefined. (See API docs for
Map.keySet(), Map.entrySet(), and Map.values().)


John Bollinger
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments