class BdbWorkQueue extends WorkQueue
implements Serializable {
    private static final long serialVersionUID = 1L;
    private static Logger LOGGER =
        Logger.getLogger(BdbWorkQueue.class.getName());


    /**
     * All items in this queue have this same 'origin'
     * prefix to their keys.
     */
    private byte[] origin;

    /**
     * Create a virtual queue inside the given BdbMultipleWorkQueues 
     * 
     * @param classKey
     */
    public BdbWorkQueue(String classKey, BdbFrontier frontier) {
        super(classKey);
        this.origin = BdbMultipleWorkQueues.calculateOriginKey(classKey);
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine(getPrefixClassKey(this.origin) + " " + classKey);
        }
        // add the queue-front 'cap' entry; see...
        // http://sourceforge.net/tracker/index.php?func=detail&aid=1262665&group_id=73833&atid=539102
        frontier.getWorkQueues().addCap(origin);
    }

    protected long deleteMatchingFromQueue(final WorkQueueFrontier frontier,
            final String match) throws IOException {
        try {
            final BdbMultipleWorkQueues queues = ((BdbFrontier) frontier)
                .getWorkQueues();
            return queues.deleteMatchingFromQueue(match, classKey,
                new DatabaseEntry(origin));
        } catch (DatabaseException e) {
            throw new IOException(e);
        }
    }

    protected void deleteItem(final WorkQueueFrontier frontier,
            final CrawlURI peekItem) throws IOException {
        try {
            final BdbMultipleWorkQueues queues = ((BdbFrontier) frontier)
                .getWorkQueues();
             queues.delete(peekItem);
        } catch (DatabaseException e) {
            throw new IOException(e);
        }
    }

    protected CrawlURI peekItem(final WorkQueueFrontier frontier)
    throws IOException {
        final BdbMultipleWorkQueues queues = ((BdbFrontier) frontier)
            .getWorkQueues();
        DatabaseEntry key = new DatabaseEntry(origin);
        CrawlURI curi = null;
        int tries = 1;
        while(true) {
            try {
                curi = queues.get(key);
            } catch (DatabaseException e) {
                LOGGER.log(Level.SEVERE,"peekItem failure; retrying",e);
            }
            
            // ensure CrawlURI, if any,  came from acceptable range: 
            if(!ArchiveUtils.startsWith(key.getData(),origin)) {
                LOGGER.severe(
                    "inconsistency: "+classKey+"("+
                    getPrefixClassKey(origin)+") with " + getCount() + " items gave "
                    + curi +"("+getPrefixClassKey(key.getData()));
                // clear curi to allow retry
                curi = null; 
                // reset key to original origin for retry
                key.setData(origin);
            }
            
            if (curi!=null) {
                // success
                break;
            }
            
            if (tries>3) {
                LOGGER.severe("no item where expected in queue "+classKey);
                break;
            }
            tries++;
            LOGGER.severe("Trying get #" + Integer.toString(tries)
                    + " in queue " + classKey + " with " + getCount()
                    + " items using key "
                    + getPrefixClassKey(key.getData()));
        }
 
        return curi;
    }

    protected void insertItem(final WorkQueueFrontier frontier,
            final CrawlURI curi, boolean overwriteIfPresent) throws IOException {<FILL_FUNCTION_BODY>}
    
    /**
     * @param byteArray Byte array to get hex string of.
     * @return Hex string of passed in byte array (Used logging
     * key-prefixes).
     */
    protected static String getPrefixClassKey(final byte [] byteArray) {
        int zeroIndex = 0;
        while(byteArray[zeroIndex]!=0) {
            zeroIndex++;
        }
        try {
            return new String(byteArray,0,zeroIndex,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            // should be impossible; UTF-8 always available
            e.printStackTrace();
            return e.getMessage();
        }
    }
    
    // Kryo support
    public static void autoregisterTo(AutoKryo kryo) {
        kryo.register(BdbWorkQueue.class);
        kryo.autoregister(FetchStats.class); 
        kryo.autoregister(HashSet.class);
        kryo.autoregister(SimplePrecedenceProvider.class);
        kryo.autoregister(byte[].class);
        kryo.setRegistrationOptional(true); 
    }
}

        try {
            final BdbMultipleWorkQueues queues = ((BdbFrontier) frontier)
                .getWorkQueues();
            queues.put(curi, overwriteIfPresent);
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine("Inserted into " + getPrefixClassKey(this.origin) +
                    " (count " + Long.toString(getCount())+ "): " +
                        curi.toString());
            }
        } catch (DatabaseException e) {
            throw new IOException(e);
        }
    
<methods>public void <init>(java.lang.String) ,public final int compareTo(java.util.concurrent.Delayed) ,public synchronized void considerActive() ,public synchronized long deleteMatching(org.archive.crawler.frontier.WorkQueueFrontier, java.lang.String) ,public void expend(int) ,public java.lang.String getClassKey() ,public synchronized long getCount() ,public long getDelay(java.util.concurrent.TimeUnit) ,public java.lang.String getKey() ,public int getPrecedence() ,public org.archive.crawler.frontier.precedence.PrecedenceProvider getPrecedenceProvider() ,public int getSessionBudget() ,public org.archive.modules.fetcher.FetchStats getSubstats() ,public long getTotalExpenditure() ,public long getWakeTime() ,public boolean isManaged() ,public boolean isOverSessionBudget() ,public boolean isOverTotalBudget() ,public boolean isRetired() ,public void makeDirty() ,public synchronized void noteDeactivated() ,public void noteError(int) ,public synchronized void noteExhausted() ,public synchronized org.archive.modules.CrawlURI peek(org.archive.crawler.frontier.WorkQueueFrontier) ,public synchronized void reportTo(java.io.PrintWriter) ,public void setIdentityCache(ObjectIdentityCache<?>) ,public void setPrecedenceProvider(org.archive.crawler.frontier.precedence.PrecedenceProvider) ,public void setWakeTime(long) ,public java.lang.String shortReportLegend() ,public java.lang.String shortReportLine() ,public synchronized void shortReportLineTo(java.io.PrintWriter) ,public synchronized Map<java.lang.String,java.lang.Object> shortReportMap() ,public void tally(org.archive.modules.CrawlURI, org.archive.modules.fetcher.FetchStats.Stage) ,public java.lang.String toString() ,public synchronized void unpeek(org.archive.modules.CrawlURI) <variables>protected boolean active,private transient ObjectIdentityCache<?> cache,protected final non-sealed java.lang.String classKey,protected long costCount,protected long count,protected long enqueueCount,protected long errorCount,protected long expenditureAtLastActivation,protected boolean isManaged,protected int lastCost,protected long lastDequeueTime,protected java.lang.String lastPeeked,protected java.lang.String lastQueued,private static final java.util.logging.Logger logger,protected transient org.archive.modules.CrawlURI peekItem,protected org.archive.crawler.frontier.precedence.PrecedenceProvider precedenceProvider,protected boolean retired,private static final long serialVersionUID,protected int sessionBudget,protected org.archive.modules.fetcher.FetchStats substats,protected long totalBudget,protected long totalExpenditure,protected long wakeTime