class DiskFPMergeUriUniqFilter extends FPMergeUriUniqFilter {
    protected long count = 0; 
    protected File scratchDir; 
    protected File currentFps;
    protected File newFpsFile;
    protected DataOutputStream newFps; 
    protected long newCount; 
    protected DataInputStream oldFps; 
    
    public DiskFPMergeUriUniqFilter(File scratchDir) {
        super();
        this.scratchDir = scratchDir; 
        // TODO: Use two scratch locations, to allow IO to be split
        // over separate disks
    }
    
    /* (non-Javadoc)
     * @see org.archive.crawler.util.FPMergeUriUniqFilter#beginFpMerge()
     */
    protected LongIterator beginFpMerge() {<FILL_FUNCTION_BODY>}

    /* (non-Javadoc)
     * @see org.archive.crawler.util.FPMergeUriUniqFilter#addNewFp(long)
     */
    protected void addNewFp(long fp) {
        try {
            newFps.writeLong(fp);
            newCount++;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /* (non-Javadoc)
     * @see org.archive.crawler.util.FPMergeUriUniqFilter#finishFpMerge()
     */
    protected void finishFpMerge() {
        try {
            newFps.close();
            File oldFpsFile = currentFps;
            currentFps = newFpsFile;
            if(oldFps!=null) {
                oldFps.close();
            }
            if(oldFpsFile!=null) {
                oldFpsFile.delete();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        count = newCount;
    }

    /* (non-Javadoc)
     * @see org.archive.crawler.datamodel.UriUniqFilter#count()
     */
    public long count() {
        return count;
    }

    public class DataFileLongIterator implements LongIterator {
        DataInputStream in; 
        long next;
        boolean nextIsValid = false; 
        
        /**
         * Construct a long iterator reading from the given 
         * stream. 
         * 
         * @param disStream DataInputStream from which to read longs
         */
        public DataFileLongIterator(DataInputStream disStream) {
            this.in = disStream;
        }

        /** 
         * Test whether any items remain; loads next item into
         * holding 'next' field. 
         * 
         * @see java.util.Iterator#hasNext()
         */
        public boolean hasNext() {
            return nextIsValid ? true: lookahead();
        }
        
        /**
         * Check if there's a next by trying to read it. 
         * 
         * @return true if 'next' field is filled with a valid next, false otherwise
         */
        protected boolean lookahead() {
            try {
                next = in.readLong();
            } catch (IOException e) {
                return false; 
            }
            nextIsValid = true; 
            return true; 
        }

        /** 
         * Return the next item.
         * 
         * @see java.util.Iterator#next()
         */
        public Long next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            // 'next' is guaranteed set by a hasNext() which returned true
            Long returnObj = new Long(this.next);
            this.nextIsValid = false;
            return returnObj;
        }
        
        /* (non-Javadoc)
         * @see java.util.Iterator#remove()
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }
        
        
        /* (non-Javadoc)
         * @see it.unimi.dsi.fastutil.longs.LongIterator#nextLong()
         */
        public long nextLong() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            // 'next' is guaranteed non-null by a hasNext() which returned true
            this.nextIsValid = false; // after this return, 'next' needs refresh
            return this.next;
        }

        /* (non-Javadoc)
         * @see it.unimi.dsi.fastutil.longs.LongIterator#skip(int)
         */
        public int skip(int arg0) {
            return 0;
        }
    }

}

        newFpsFile = new File(scratchDir,ArchiveUtils.get17DigitDate()+".fp");
        if(newFpsFile.exists()) {
            throw new RuntimeException(newFpsFile+" exists");
        }
        try {
            newFps = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newFpsFile)));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        newCount = 0;
        if(currentFps==null) {
            return LongIterators.EMPTY_ITERATOR;
        }
        try {
            oldFps = new DataInputStream(new BufferedInputStream(new FileInputStream(currentFps)));
        } catch (FileNotFoundException e1) {
            throw new RuntimeException(e1);
        }
        return new DataFileLongIterator(oldFps);
    
<methods>public void <init>() ,public synchronized void add(java.lang.String, org.archive.modules.CrawlURI) ,public void addForce(java.lang.String, org.archive.modules.CrawlURI) ,public void addNow(java.lang.String, org.archive.modules.CrawlURI) ,public long addedCount() ,public void close() ,public static long createFp(java.lang.CharSequence) ,public synchronized long flush() ,public void forget(java.lang.String, org.archive.modules.CrawlURI) ,public void note(java.lang.String) ,public long pending() ,public synchronized long requestFlush() ,public void setDestination(org.archive.crawler.datamodel.UriUniqFilter.CrawlUriReceiver) ,public void setMaxPending(int) ,public void setProfileLog(java.io.File) <variables>public static final int DEFAULT_MAX_PENDING,public static final long FLUSH_DELAY_FACTOR,private static java.util.logging.Logger LOGGER,protected java.util.concurrent.atomic.AtomicLong addedCount,protected int maxPending,protected long mergeDupAtLast,protected long mergeDuplicateCount,protected long nextFlushAllowableAfter,protected long pendDupAtLast,protected long pendDuplicateCount,protected TreeSet<org.archive.crawler.util.FPMergeUriUniqFilter.PendingItem> pendingSet,protected java.io.PrintWriter profileLog,protected org.archive.util.fingerprint.ArrayLongFPCache quickCache,protected long quickDupAtLast,protected long quickDuplicateCount,protected org.archive.crawler.datamodel.UriUniqFilter.CrawlUriReceiver receiver