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

Reply via email to