Update of /cvsroot/freenet/freenet/src/freenet/support
In directory sc8-pr-cvs1:/tmp/cvs-serv4057/src/freenet/support
Added Files:
PooledRandomAccessFile.java RandomAccessFilePool.java
Log Message:
6236:
Add support for a maximum number of FDs used for open files by NativeFSDir, with
pooling.
Remove reference to BlackLRUQueue in OCM - not used any more, was a dirty hack.
Throw an NPE slightly earlier in some code tracking bug in.
--- NEW FILE: PooledRandomAccessFile.java ---
package freenet.support;
import java.io.*;
/**
* Interface for pooled RandomAccessFile-like objects.
* Purpose of pooling is to save FDs.
* Classes implementing this interface should be synchronized.
* @see RandomAccessFilePool
*/
public interface PooledRandomAccessFile {
public long length() throws IOException;
public void seek(long pos) throws IOException;
/** Synchronize. Provided to avoid requiring locking in client.
* In java.io.RandomAccessFile this would go via the FileDescriptor.
*/
public void sync() throws IOException;
public int read() throws IOException;
public int read(byte[] b, int off, int len) throws IOException;
public void write(int b) throws IOException;
public void write(byte[] b, int off, int len) throws IOException;
public long getFilePointer() throws IOException;
/** Close the underlying RandomAccessFile, if we are short on
* handles. Call this when you have temporarily finished with a
* RAF, but don't want to close() yet.
*/
public void closeRAF();
public void close() throws IOException;
}
--- NEW FILE: RandomAccessFilePool.java ---
package freenet.support;
import java.io.*;
/**
* A pool of PooledRandomAccessFiles. These are similar to
* java.io.RandomAccessFiles, but we have a maximum number of file
* descriptors. If there are more RAFs than that allocated, we keep only
* the MRU fds open.
*
* Synchronized.
*/
public class RandomAccessFilePool {
int maxOpenFiles;
volatile int totalOpenFiles;
LRUQueue queue;
public RandomAccessFilePool(int maxFDsOpen) {
this.maxOpenFiles = maxFDsOpen;
queue = new LRUQueue();
if(maxFDsOpen < 2) throw new IllegalArgumentException("Unreasonable maximum
number of open files "+maxFDsOpen);
}
public PooledRandomAccessFile open(File f, String mode)
throws IOException {
return new MyPooledRandomAccessFile(f, mode);
}
public int totalOpenFiles() {
return totalOpenFiles;
}
class MyPooledRandomAccessFile implements PooledRandomAccessFile {
File filename;
String mode;
RandomAccessFile raf;
boolean closed = false;
long position = 0; // Not guaranteed to be up to date unless raf closed
public MyPooledRandomAccessFile(File f, String mode) throws IOException {
this.filename = f;
this.mode = mode;
reopen();
}
synchronized void reopen() throws IOException {
if(raf == null) {
if(closed) throw new IOException("Already closed or failed to save
position");
synchronized(RandomAccessFilePool.this) {
totalOpenFiles++;
queue.push(this);
if(totalOpenFiles > maxOpenFiles) {
PooledRandomAccessFile fClose =
(PooledRandomAccessFile)(queue.pop());
// Close LRU
// Since this is LRU we shouldn't have lock contention
if(fClose == this)
throw new IllegalStateException("aaaaargh! Popped self!");
fClose.closeRAF();
}
}
raf = new RandomAccessFile(filename, mode);
if(position != 0) {
raf.seek(position);
}
}
}
public long length() throws IOException {
synchronized(this) {
if(raf != null)
return raf.length();
}
return filename.length();
}
public synchronized void seek(long pos) throws IOException {
reopen();
raf.seek(pos);
position = pos;
}
/**
* Not in RandomAccessFile API, but because of synchronization
* issues, it is better to put it here */
public synchronized void sync() throws IOException {
// No need to reopen
if(raf != null) {
raf.getFD().sync();
}
}
public synchronized int read() throws IOException {
reopen();
return raf.read();
}
public synchronized int read(byte[] buf, int off, int len)
throws IOException {
reopen();
return raf.read(buf, off, len);
}
public synchronized void write(int b) throws IOException {
reopen();
raf.write(b);
}
public synchronized void write(byte[] b, int offset, int len)
throws IOException {
reopen();
raf.write(b, offset, len);
}
public synchronized long getFilePointer() throws IOException {
if(raf == null)
return position;
else
return raf.getFilePointer();
}
public synchronized void closeRAF() {
if(raf == null) return;
synchronized(RandomAccessFilePool.this) {
if(totalOpenFiles < maxOpenFiles)
return;
}
try {
position = raf.getFilePointer();
} catch (IOException e) {
closed = true;
}
try {
raf.close();
} catch (IOException e) {}
synchronized(RandomAccessFilePool.this) {
totalOpenFiles--;
}
raf = null;
}
public synchronized void close() throws IOException {
closed = true;
raf.close();
raf = null;
synchronized(RandomAccessFilePool.this) {
totalOpenFiles--;
}
}
}
}
_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs