libjdbm-java-1.0.orig/0000775000175000017500000000000010276576000014576 5ustar twernertwernerlibjdbm-java-1.0.orig/lib/0000775000175000017500000000000010276576000015344 5ustar twernertwernerlibjdbm-java-1.0.orig/src/0000775000175000017500000000000010276576000015365 5ustar twernertwernerlibjdbm-java-1.0.orig/src/etc/0000775000175000017500000000000010276576000016140 5ustar twernertwernerlibjdbm-java-1.0.orig/src/etc/MANIFEST.MF0000644000175000017500000000035710276576000017575 0ustar twernertwernerManifest-Version: 1.0 Specification-Title: JDBM Specification-Vendor: JDBM at SourceForge Project Specification-Version: 0.09 Implementation-Title: JDBM Implementation-Vendor: JDBM at SourceForge Project Implementation-Version: $VERSION$ libjdbm-java-1.0.orig/src/examples/0000775000175000017500000000000010276576000017203 5ustar twernertwernerlibjdbm-java-1.0.orig/src/examples/FamousPeople.java0000644000175000017500000001143110276576000022443 0ustar twernertwerner import java.util.Properties; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.helper.Tuple; import jdbm.helper.TupleBrowser; import jdbm.helper.StringComparator; import jdbm.btree.BTree; /** * Famous People example. *

* Demonstrates the use of B+Tree data structure to manage a list of * people and their occupation. The example covers insertion, * ordered traversal, reverse traversal and range lookup of records. * * @author Alex Boisvert * @version $Id: FamousPeople.java,v 1.6 2003/10/21 15:32:02 boisvert Exp $ */ public class FamousPeople { static String DATABASE = "people"; static String BTREE_NAME = "FamousPeople"; static String[] people = { "Greenspan, Alan", "Williams-Byrd, Julie", "Picasso, Pablo", "Stallman, Richard", "Fort, Paul", "Søndergaard, Ole", "Schwarzenegger, Arnold", "Dulkinys, Susanna" }; static String[] occupations = { "Federal Reserve Board Chairman", "Engineer", "Painter", "Programmer", "Poet", "Typographer", "Actor", "Designer" }; static String PREFIX = "S"; /** * Example main entrypoint. */ public static void main( String[] args ) { RecordManager recman; long recid; Tuple tuple = new Tuple(); TupleBrowser browser; BTree tree; Properties props; props = new Properties(); try { // open database and setup an object cache recman = RecordManagerFactory.createRecordManager( DATABASE, props ); // try to reload an existing B+Tree recid = recman.getNamedObject( BTREE_NAME ); if ( recid != 0 ) { tree = BTree.load( recman, recid ); System.out.println( "Reloaded existing BTree with " + tree.size() + " famous people." ); } else { // create a new B+Tree data structure and use a StringComparator // to order the records based on people's name. tree = BTree.createInstance( recman, new StringComparator() ); recman.setNamedObject( BTREE_NAME, tree.getRecid() ); System.out.println( "Created a new empty BTree" ); } // insert people with their respective occupation System.out.println(); for ( int i=0; i 0 ) { buf.append( ' ' ); } return buf.toString(); } } libjdbm-java-1.0.orig/src/examples/FruitBasket.java0000644000175000017500000000704110276576000022271 0ustar twernertwerner import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.helper.FastIterator; import jdbm.htree.HTree; import java.io.IOException; import java.util.Properties; /** * Sample JDBM application to demonstrate the use of basic JDBM operations. * * @author Alex Boisvert * @version $Id: FruitBasket.java,v 1.3 2003/08/06 20:10:15 boisvert Exp $ */ public class FruitBasket { RecordManager recman; HTree hashtable; FastIterator iter; String fruit; String color; public FruitBasket() throws IOException { // create or open fruits record manager Properties props = new Properties(); recman = RecordManagerFactory.createRecordManager( "fruits", props ); // create or load fruit basket (hashtable of fruits) long recid = recman.getNamedObject( "basket" ); if ( recid != 0 ) { System.out.println( "Reloading existing fruit basket..." ); hashtable = HTree.load( recman, recid ); showBasket(); } else { System.out.println( "Creating new fruit basket..." ); hashtable = HTree.createInstance( recman ); recman.setNamedObject( "basket", hashtable.getRecid() ); } } public void runDemo() throws IOException { // insert keys and values System.out.println(); System.out.println( "Adding fruits to the basket..." ); hashtable.put( "bananas", "yellow" ); hashtable.put( "strawberries", "red" ); hashtable.put( "kiwis", "green" ); showBasket(); // display color of a specific fruit System.out.println(); System.out.println( "Get the color of bananas..." ); String bananasColor = (String) hashtable.get( "bananas" ); System.out.println( "bananas are " + bananasColor ); recman.commit(); try { // Thread.sleep( 10 * 1000 ); } catch ( Exception except ) { // ignore } // remove a specific fruit from hashtable System.out.println(); System.out.print( "Removing bananas from the basket..." ); hashtable.remove( "bananas" ); recman.commit(); System.out.println( " done." ); // iterate over remaining objects System.out.println(); System.out.println( "Remaining fruit colors:" ); iter = hashtable.keys(); fruit = (String) iter.next(); while ( fruit != null ) { color = (String) hashtable.get( fruit ); System.out.println( fruit + " are " + color ); fruit = (String) iter.next(); } // cleanup recman.close(); } public void showBasket() throws IOException { // Display content of fruit basket System.out.println(); System.out.print( "Fruit basket contains: " ); iter = hashtable.keys(); fruit = (String) iter.next(); while ( fruit != null ) { System.out.print( " " + fruit ); fruit = (String) iter.next(); } System.out.println(); } public static void main( String[] args ) { try { FruitBasket basket = new FruitBasket(); basket.runDemo(); } catch ( IOException ioe ) { ioe.printStackTrace(); } } } libjdbm-java-1.0.orig/src/examples/Primes.java0000644000175000017500000002006510276576000021306 0ustar twernertwerner import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.RecordManagerOptions; import jdbm.btree.BTree; import jdbm.helper.LongComparator; import jdbm.helper.Tuple; import jdbm.helper.TupleBrowser; import java.util.Properties; import java.util.Random; import java.io.IOException; /** * Example program dealing with B+Trees and Prime numbers. */ public class Primes { /** * Default number of prime number to populate in the database (if not specified on command-line) */ public static int DEFAULT_POPULATE = 100; /** * Default number of random lookups (if not specified on command-line) */ public static int DEFAULT_LOOKUPS = 100; /** * Record Manager used for persistence. */ private RecordManager _recman; /** * B+Tree holding prime numbers. */ private BTree _primes; /** * Random number generator. */ private static Random _random = new Random(); /** * Main constructor */ public Primes( String[] args ) throws IOException { long recid; Properties props; // open database and setup an object cache props = new Properties(); props.put( RecordManagerOptions.CACHE_SIZE, "10000" ); _recman = RecordManagerFactory.createRecordManager( "primes", props ); recid = _recman.getNamedObject( "primes" ); if ( recid == 0 ) { System.out.println( "Creating a new primes B+Tree." ); _primes = BTree.createInstance( _recman, new LongComparator() ); _recman.setNamedObject( "primes", _primes.getRecid() ); } else { _primes = BTree.load( _recman, recid ); System.out.println( "B+Tree already contains " + _primes.size() + " primes." ); } _recman.commit(); } /** * Get the largest prime number in the database. */ public Long getLargestPrime() throws IOException { Tuple tuple; TupleBrowser browser; Long largest = null; tuple = new Tuple(); browser = _primes.browse( null ); if ( browser.getPrevious( tuple ) ) { largest = (Long) tuple.getValue(); System.out.println( "Largest prime: " + largest ); } else { System.out.println( "No prime number in the database." ); } return largest; } /** * Populate the database with more prime numbers. * * @param count Number of primes to add to database. */ void populate( int count ) throws IOException { Long current; Long largest; System.out.println( "Populating prime B+Tree..." ); // start after the largest known prime largest = getLargestPrime(); if ( largest == null ) { largest = new Long( 0 ); } current = new Long( largest.longValue() + 1L ); while ( count > 0 ) { if ( isPrime( current ) ) { _primes.insert( current, current, false ); System.out.println( "Found prime #" + _primes.size() + ": " + current ); count--; } current = new Long( current.longValue() + 1 ); } _recman.commit(); } /** * Returns true if a number is prime. */ boolean isPrime( Long number ) throws IOException { Tuple tuple; TupleBrowser browser; Long largest; Long current; if ( number.longValue() <= 0L ) { throw new IllegalArgumentException( "Number must be greater than zero" ); } if ( number.longValue() == 1 ) { return true; } tuple = new Tuple(); browser = _primes.browse(); while ( browser.getNext( tuple ) ) { current = (Long) tuple.getValue(); if ( current.longValue() != 1 && ( number.longValue() % current.longValue() ) == 0 ) { // not a prime because it is divisibe by a prime return false; } } // this is a prime return true; } /** * Display a number of random prime numbers. */ void random( int count ) throws IOException { Tuple tuple; TupleBrowser browser; Long largest; Long number; tuple = new Tuple(); largest = getLargestPrime(); System.out.println( "Looking up " + count + " random primes...." ); long start = System.currentTimeMillis(); for ( int i=0; i primes.getLargestPrime().longValue() ) { throw new IllegalArgumentException( "Number is larger than largest known prime in database." ); } if ( primes.isPrime( number ) ) { System.out.println( "The number " + number + " is a prime." ); } else { System.out.println( "The number " + number + " is not a prime." ); } } else if ( args[i].equalsIgnoreCase( "-random" ) ) { if ( ++i < args.length ) { count = Integer.parseInt( args[i] ); } else { count = DEFAULT_LOOKUPS; } primes.random( count ); } } if ( args.length == 0 ) { System.out.println( "Usage: java Prime [action] [args]" ); System.out.println( "" ); System.out.println( "Actions:" ); System.out.println( " -populate [number] Populate database with prime numbers" ); System.out.println( " -check [number] Check if a number is a prime" ); System.out.println( " -random [number] Display random prime numbers" ); System.out.println( "" ); } } catch ( IOException except ) { except.printStackTrace(); } } } libjdbm-java-1.0.orig/src/main/0000775000175000017500000000000010276576000016311 5ustar twernertwernerlibjdbm-java-1.0.orig/src/main/jdbm/0000775000175000017500000000000010276576000017225 5ustar twernertwernerlibjdbm-java-1.0.orig/src/main/jdbm/btree/0000775000175000017500000000000010276576000020326 5ustar twernertwernerlibjdbm-java-1.0.orig/src/main/jdbm/btree/BPage.java0000644000175000017500000011467410276576000022162 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.btree; import jdbm.helper.Serializer; import jdbm.helper.Tuple; import jdbm.helper.TupleBrowser; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * Page of a Btree. *

* The page contains a number of key-value pairs. Keys are ordered to allow * dichotomic search. *

* If the page is a leaf page, the keys and values are user-defined and * represent entries inserted by the user. *

* If the page is non-leaf, each key represents the greatest key in the * underlying BPages and the values are recids pointing to the children BPages. * The only exception is the rightmost BPage, which is considered to have an * "infinite" key value, meaning that any insert will be to the left of this * pseudo-key * * @author Alex Boisvert * @version $Id: BPage.java,v 1.6 2003/09/21 15:46:59 boisvert Exp $ */ public final class BPage implements Serializer { private static final boolean DEBUG = false; /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Parent B+Tree. */ transient BTree _btree; /** * This BPage's record ID in the PageManager. */ protected transient long _recid; /** * Flag indicating if this is a leaf BPage. */ protected boolean _isLeaf; /** * Keys of children nodes */ protected Object[] _keys; /** * Values associated with keys. (Only valid if leaf BPage) */ protected Object[] _values; /** * Children pages (recids) associated with keys. (Only valid if non-leaf BPage) */ protected long[] _children; /** * Index of first used item at the page */ protected int _first; /** * Previous leaf BPage (only if this BPage is a leaf) */ protected long _previous; /** * Next leaf BPage (only if this BPage is a leaf) */ protected long _next; /** * No-argument constructor used by serialization. */ public BPage() { // empty } /** * Root page overflow constructor */ BPage( BTree btree, BPage root, BPage overflow ) throws IOException { _btree = btree; _isLeaf = false; _first = _btree._pageSize-2; _keys = new Object[ _btree._pageSize ]; _keys[ _btree._pageSize-2 ] = overflow.getLargestKey(); _keys[ _btree._pageSize-1 ] = root.getLargestKey(); _children = new long[ _btree._pageSize ]; _children[ _btree._pageSize-2 ] = overflow._recid; _children[ _btree._pageSize-1 ] = root._recid; _recid = _btree._recman.insert( this, this ); } /** * Root page (first insert) constructor. */ BPage( BTree btree, Object key, Object value ) throws IOException { _btree = btree; _isLeaf = true; _first = btree._pageSize-2; _keys = new Object[ _btree._pageSize ]; _keys[ _btree._pageSize-2 ] = key; _keys[ _btree._pageSize-1 ] = null; // I am the root BPage for now _values = new Object[ _btree._pageSize ]; _values[ _btree._pageSize-2 ] = value; _values[ _btree._pageSize-1 ] = null; // I am the root BPage for now _recid = _btree._recman.insert( this, this ); } /** * Overflow page constructor. Creates an empty BPage. */ BPage( BTree btree, boolean isLeaf ) throws IOException { _btree = btree; _isLeaf = isLeaf; // page will initially be half-full _first = _btree._pageSize/2; _keys = new Object[ _btree._pageSize ]; if ( isLeaf ) { _values = new Object[ _btree._pageSize ]; } else { _children = new long[ _btree._pageSize ]; } _recid = _btree._recman.insert( this, this ); } /** * Get largest key under this BPage. Null is considered to be the * greatest possible key. */ Object getLargestKey() { return _keys[ _btree._pageSize-1 ]; } /** * Return true if BPage is empty. */ boolean isEmpty() { if ( _isLeaf ) { return ( _first == _values.length-1 ); } else { return ( _first == _children.length-1 ); } } /** * Return true if BPage is full. */ boolean isFull() { return ( _first == 0 ); } /** * Find the object associated with the given key. * * @param height Height of the current BPage (zero is leaf page) * @param key The key * @return TupleBrowser positionned just before the given key, or before * next greater key if key isn't found. */ TupleBrowser find( int height, Object key ) throws IOException { int index = findChildren( key ); /* if ( DEBUG ) { System.out.println( "BPage.find() current: " + this + " height: " + height); } */ height -= 1; if ( height == 0 ) { // leaf BPage return new Browser( this, index ); } else { // non-leaf BPage BPage child = childBPage( index ); return child.find( height, key ); } } /** * Find first entry and return a browser positioned before it. * * @return TupleBrowser positionned just before the first entry. */ TupleBrowser findFirst() throws IOException { if ( _isLeaf ) { return new Browser( this, _first ); } else { BPage child = childBPage( _first ); return child.findFirst(); } } /** * Insert the given key and value. *

* Since the Btree does not support duplicate entries, the caller must * specify whether to replace the existing value. * * @param height Height of the current BPage (zero is leaf page) * @param key Insert key * @param value Insert value * @param replace Set to true to replace the existing value, if one exists. * @return Insertion result containing existing value OR a BPage if the key * was inserted and provoked a BPage overflow. */ InsertResult insert( int height, Object key, Object value, boolean replace ) throws IOException { InsertResult result; long overflow; int index = findChildren( key ); height -= 1; if ( height == 0 ) { result = new InsertResult(); // inserting on a leaf BPage overflow = -1; if ( DEBUG ) { System.out.println( "Bpage.insert() Insert on leaf Bpage key=" + key + " value=" + value + " index="+index); } if ( compare( key, _keys[ index ] ) == 0 ) { // key already exists if ( DEBUG ) { System.out.println( "Bpage.insert() Key already exists." ) ; } result._existing = _values[ index ]; if ( replace ) { _values [ index ] = value; _btree._recman.update( _recid, this, this ); } // return the existing key return result; } } else { // non-leaf BPage BPage child = childBPage( index ); result = child.insert( height, key, value, replace ); if ( result._existing != null ) { // return existing key, if any. return result; } if ( result._overflow == null ) { // no overflow means we're done with insertion return result; } // there was an overflow, we need to insert the overflow page // on this BPage if ( DEBUG ) { System.out.println( "BPage.insert() Overflow page: " + result._overflow._recid ); } key = result._overflow.getLargestKey(); overflow = result._overflow._recid; // update child's largest key _keys[ index ] = child.getLargestKey(); // clean result so we can reuse it result._overflow = null; } // if we get here, we need to insert a new entry on the BPage // before _children[ index ] if ( !isFull() ) { if ( height == 0 ) { insertEntry( this, index-1, key, value ); } else { insertChild( this, index-1, key, overflow ); } _btree._recman.update( _recid, this, this ); return result; } // page is full, we must divide the page int half = _btree._pageSize >> 1; BPage newPage = new BPage( _btree, _isLeaf ); if ( index < half ) { // move lower-half of entries to overflow BPage, // including new entry if ( DEBUG ) { System.out.println( "Bpage.insert() move lower-half of entries to overflow BPage, including new entry." ) ; } if ( height == 0 ) { copyEntries( this, 0, newPage, half, index ); setEntry( newPage, half+index, key, value ); copyEntries( this, index, newPage, half+index+1, half-index-1 ); } else { copyChildren( this, 0, newPage, half, index ); setChild( newPage, half+index, key, overflow ); copyChildren( this, index, newPage, half+index+1, half-index-1 ); } } else { // move lower-half of entries to overflow BPage, // new entry stays on this BPage if ( DEBUG ) { System.out.println( "Bpage.insert() move lower-half of entries to overflow BPage. New entry stays" ) ; } if ( height == 0 ) { copyEntries( this, 0, newPage, half, half ); copyEntries( this, half, this, half-1, index-half ); setEntry( this, index-1, key, value ); } else { copyChildren( this, 0, newPage, half, half ); copyChildren( this, half, this, half-1, index-half ); setChild( this, index-1, key, overflow ); } } _first = half-1; // nullify lower half of entries for ( int i=0; i<_first; i++ ) { if ( height == 0 ) { setEntry( this, i, null, null ); } else { setChild( this, i, null, -1 ); } } if ( _isLeaf ) { // link newly created BPage newPage._previous = _previous; newPage._next = _recid; if ( _previous != 0 ) { BPage previous = loadBPage( _previous ); previous._next = newPage._recid; _btree._recman.update( _previous, previous, this ); } _previous = newPage._recid; } _btree._recman.update( _recid, this, this ); _btree._recman.update( newPage._recid, newPage, this ); result._overflow = newPage; return result; } /** * Remove the entry associated with the given key. * * @param height Height of the current BPage (zero is leaf page) * @param key Removal key * @return Remove result object */ RemoveResult remove( int height, Object key ) throws IOException { RemoveResult result; int half = _btree._pageSize / 2; int index = findChildren( key ); height -= 1; if ( height == 0 ) { // remove leaf entry if ( compare( _keys[ index ], key ) != 0 ) { throw new IllegalArgumentException( "Key not found: " + key ); } result = new RemoveResult(); result._value = _values[ index ]; removeEntry( this, index ); // update this BPage _btree._recman.update( _recid, this, this ); } else { // recurse into Btree to remove entry on a children page BPage child = childBPage( index ); result = child.remove( height, key ); // update children _keys[ index ] = child.getLargestKey(); _btree._recman.update( _recid, this, this ); if ( result._underflow ) { // underflow occured if ( child._first != half+1 ) { throw new IllegalStateException( "Error during underflow [1]" ); } if ( index < _children.length-1 ) { // exists greater brother page BPage brother = childBPage( index+1 ); int bfirst = brother._first; if ( bfirst < half ) { // steal entries from "brother" page int steal = ( half - bfirst + 1 ) / 2; brother._first += steal; child._first -= steal; if ( child._isLeaf ) { copyEntries( child, half+1, child, half+1-steal, half-1 ); copyEntries( brother, bfirst, child, 2*half-steal, steal ); } else { copyChildren( child, half+1, child, half+1-steal, half-1 ); copyChildren( brother, bfirst, child, 2*half-steal, steal ); } for ( int i=bfirst; i half; return result; } /** * Find the first children node with a key equal or greater than the given * key. * * @return index of first children with equal or greater key. */ private int findChildren( Object key ) { int left = _first; int right = _btree._pageSize-1; // binary search while ( left < right ) { int middle = ( left + right ) / 2; if ( compare( _keys[ middle ], key ) < 0 ) { left = middle+1; } else { right = middle; } } return right; } /** * Insert entry at given position. */ private static void insertEntry( BPage page, int index, Object key, Object value ) { Object[] keys = page._keys; Object[] values = page._values; int start = page._first; int count = index-page._first+1; // shift entries to the left System.arraycopy( keys, start, keys, start-1, count ); System.arraycopy( values, start, values, start-1, count ); page._first -= 1; keys[ index ] = key; values[ index ] = value; } /** * Insert child at given position. */ private static void insertChild( BPage page, int index, Object key, long child ) { Object[] keys = page._keys; long[] children = page._children; int start = page._first; int count = index-page._first+1; // shift entries to the left System.arraycopy( keys, start, keys, start-1, count ); System.arraycopy( children, start, children, start-1, count ); page._first -= 1; keys[ index ] = key; children[ index ] = child; } /** * Remove entry at given position. */ private static void removeEntry( BPage page, int index ) { Object[] keys = page._keys; Object[] values = page._values; int start = page._first; int count = index-page._first; System.arraycopy( keys, start, keys, start+1, count ); keys[ start ] = null; System.arraycopy( values, start, values, start+1, count ); values[ start ] = null; page._first++; } /** * Remove child at given position. */ /* private static void removeChild( BPage page, int index ) { Object[] keys = page._keys; long[] children = page._children; int start = page._first; int count = index-page._first; System.arraycopy( keys, start, keys, start+1, count ); keys[ start ] = null; System.arraycopy( children, start, children, start+1, count ); children[ start ] = (long) -1; page._first++; } */ /** * Set the entry at the given index. */ private static void setEntry( BPage page, int index, Object key, Object value ) { page._keys[ index ] = key; page._values[ index ] = value; } /** * Set the child BPage recid at the given index. */ private static void setChild( BPage page, int index, Object key, long recid ) { page._keys[ index ] = key; page._children[ index ] = recid; } /** * Copy entries between two BPages */ private static void copyEntries( BPage source, int indexSource, BPage dest, int indexDest, int count ) { System.arraycopy( source._keys, indexSource, dest._keys, indexDest, count); System.arraycopy( source._values, indexSource, dest._values, indexDest, count); } /** * Copy child BPage recids between two BPages */ private static void copyChildren( BPage source, int indexSource, BPage dest, int indexDest, int count ) { System.arraycopy( source._keys, indexSource, dest._keys, indexDest, count); System.arraycopy( source._children, indexSource, dest._children, indexDest, count); } /** * Return the child BPage at given index. */ BPage childBPage( int index ) throws IOException { return loadBPage( _children[ index ] ); } /** * Load the BPage at the given recid. */ private BPage loadBPage( long recid ) throws IOException { BPage child = (BPage) _btree._recman.fetch( recid, this ); child._recid = recid; child._btree = _btree; return child; } private final int compare( Object value1, Object value2 ) { if ( value1 == null ) { return 1; } if ( value2 == null ) { return -1; } return _btree._comparator.compare( value1, value2 ); } static byte[] readByteArray( ObjectInput in ) throws IOException { int len = in.readInt(); if ( len < 0 ) { return null; } byte[] buf = new byte[ len ]; in.readFully( buf ); return buf; } static void writeByteArray( ObjectOutput out, byte[] buf ) throws IOException { if ( buf == null ) { out.writeInt( -1 ); } else { out.writeInt( buf.length ); out.write( buf ); } } /** * Dump the structure of the tree on the screen. This is used for debugging * purposes only. */ private void dump( int height ) { String prefix = ""; for ( int i=0; i 0 ) { for ( int i=_first; i<_btree._pageSize; i++ ) { if ( _keys[ i ] == null ) break; BPage child = childBPage( i ); child.dump( level ); child.dumpRecursive( height, level ); } } } /** * Assert the ordering of the keys on the BPage. This is used for testing * purposes only. */ private void assertConsistency() { for ( int i=_first; i<_btree._pageSize-1; i++ ) { if ( compare( (byte[]) _keys[ i ], (byte[]) _keys[ i+1 ] ) >= 0 ) { dump( 0 ); throw new Error( "BPage not ordered" ); } } } /** * Recursively assert the ordering of the BPage entries on this page * and sub-pages. This is used for testing purposes only. */ void assertConsistencyRecursive( int height ) throws IOException { assertConsistency(); if ( --height > 0 ) { for ( int i=_first; i<_btree._pageSize; i++ ) { if ( _keys[ i ] == null ) break; BPage child = childBPage( i ); if ( compare( (byte[]) _keys[ i ], child.getLargestKey() ) != 0 ) { dump( 0 ); child.dump( 0 ); throw new Error( "Invalid child subordinate key" ); } child.assertConsistencyRecursive( height ); } } } /** * Deserialize the content of an object from a byte array. * * @param serialized Byte array representation of the object * @return deserialized object * */ public Object deserialize( byte[] serialized ) throws IOException { ByteArrayInputStream bais; ObjectInputStream ois; BPage bpage; bpage = new BPage(); bais = new ByteArrayInputStream( serialized ); ois = new ObjectInputStream( bais ); bpage._isLeaf = ois.readBoolean(); if ( bpage._isLeaf ) { bpage._previous = ois.readLong(); bpage._next = ois.readLong(); } bpage._first = ois.readInt(); bpage._keys = new Object[ _btree._pageSize ]; try { for ( int i=bpage._first; i<_btree._pageSize; i++ ) { if ( _btree._keySerializer == null ) { bpage._keys[ i ] = ois.readObject(); } else { serialized = readByteArray( ois ); if ( serialized != null ) { bpage._keys[ i ] = _btree._keySerializer.deserialize( serialized ); } } } } catch ( ClassNotFoundException except ) { throw new IOException( except.getMessage() ); } if ( bpage._isLeaf ) { bpage._values = new Object[ _btree._pageSize ]; try { for ( int i=bpage._first; i<_btree._pageSize; i++ ) { if ( _btree._valueSerializer == null ) { bpage._values[ i ] = ois.readObject(); } else { serialized = readByteArray( ois ); if ( serialized != null ) { bpage._values[ i ] = _btree._valueSerializer.deserialize( serialized ); } } } } catch ( ClassNotFoundException except ) { throw new IOException( except.getMessage() ); } } else { bpage._children = new long[ _btree._pageSize ]; for ( int i=bpage._first; i<_btree._pageSize; i++ ) { bpage._children[ i ] = ois.readLong(); } } ois.close(); bais.close(); return bpage; } /** * Serialize the content of an object into a byte array. * * @param obj Object to serialize * @return a byte array representing the object's state * */ public byte[] serialize( Object obj ) throws IOException { byte[] serialized; ByteArrayOutputStream baos; ObjectOutputStream oos; BPage bpage; byte[] data; // note: It is assumed that BPage instance doing the serialization is the parent // of the BPage object being serialized. bpage = (BPage) obj; baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream( baos ); oos.writeBoolean( bpage._isLeaf ); if ( bpage._isLeaf ) { oos.writeLong( bpage._previous ); oos.writeLong( bpage._next ); } oos.writeInt( bpage._first ); for ( int i=bpage._first; i<_btree._pageSize; i++ ) { if ( _btree._keySerializer == null ) { oos.writeObject( bpage._keys[ i ] ); } else { if ( bpage._keys[ i ] != null ) { serialized = _btree._keySerializer.serialize( bpage._keys[ i ] ); writeByteArray( oos, serialized ); } else { writeByteArray( oos, null ); } } } if ( bpage._isLeaf ) { for ( int i=bpage._first; i<_btree._pageSize; i++ ) { if ( _btree._valueSerializer == null ) { oos.writeObject( bpage._values[ i ] ); } else { if ( bpage._values[ i ] != null ) { serialized = _btree._valueSerializer.serialize( bpage._values[ i ] ); writeByteArray( oos, serialized ); } else { writeByteArray( oos, null ); } } } } else { for ( int i=bpage._first; i<_btree._pageSize; i++ ) { oos.writeLong( bpage._children[ i ] ); } } oos.flush(); data = baos.toByteArray(); oos.close(); baos.close(); return data; } /** STATIC INNER CLASS * Result from insert() method call */ static class InsertResult { /** * Overflow page. */ BPage _overflow; /** * Existing value for the insertion key. */ Object _existing; } /** STATIC INNER CLASS * Result from remove() method call */ static class RemoveResult { /** * Set to true if underlying pages underflowed */ boolean _underflow; /** * Removed entry value */ Object _value; } /** PRIVATE INNER CLASS * Browser to traverse leaf BPages. */ static class Browser extends TupleBrowser { /** * Current page. */ private BPage _page; /** * Current index in the page. The index positionned on the next * tuple to return. */ private int _index; /** * Create a browser. * * @param page Current page * @param index Position of the next tuple to return. */ Browser( BPage page, int index ) { _page = page; _index = index; } public boolean getNext( Tuple tuple ) throws IOException { if ( _index < _page._btree._pageSize ) { if ( _page._keys[ _index ] == null ) { // reached end of the tree. return false; } } else if ( _page._next != 0 ) { // move to next page _page = _page.loadBPage( _page._next ); _index = _page._first; } tuple.setKey( _page._keys[ _index ] ); tuple.setValue( _page._values[ _index ] ); _index++; return true; } public boolean getPrevious( Tuple tuple ) throws IOException { if ( _index == _page._first ) { if ( _page._previous != 0 ) { _page = _page.loadBPage( _page._previous ); _index = _page._btree._pageSize; } else { // reached beginning of the tree return false; } } _index--; tuple.setKey( _page._keys[ _index ] ); tuple.setValue( _page._values[ _index ] ); return true; } } } libjdbm-java-1.0.orig/src/main/jdbm/btree/BTree.java0000644000175000017500000004370510276576000022201 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.btree; import jdbm.RecordManager; import jdbm.helper.Serializer; import jdbm.helper.Tuple; import jdbm.helper.TupleBrowser; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; import java.util.Comparator; /** * B+Tree persistent indexing data structure. B+Trees are optimized for * block-based, random I/O storage because they store multiple keys on * one tree node (called BPage). In addition, the leaf nodes * directly contain (inline) the values associated with the keys, allowing a * single (or sequential) disk read of all the values on the page. *

* B+Trees are n-airy, yeilding log(N) search cost. They are self-balancing, * preventing search performance degradation when the size of the tree grows. *

* Keys and associated values must be Serializable objects. The * user is responsible to supply a serializable Comparator object * to be used for the ordering of entries, which are also called Tuple. * The B+Tree allows traversing the keys in forward and reverse order using a * TupleBrowser obtained from the browse() methods. *

* This implementation does not directly support duplicate keys, but it is * possible to handle duplicates by inlining or referencing an object collection * as a value. *

* There is no limit on key size or value size, but it is recommended to keep * both as small as possible to reduce disk I/O. This is especially true for * the key size, which impacts all non-leaf BPage objects. * * @author Alex Boisvert * @version $Id: BTree.java,v 1.6 2005/06/25 23:12:31 doomdark Exp $ */ public class BTree implements Externalizable { private static final boolean DEBUG = false; /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Default page size (number of entries per node) */ public static final int DEFAULT_SIZE = 16; /** * Page manager used to persist changes in BPages */ protected transient RecordManager _recman; /** * This BTree's record ID in the PageManager. */ private transient long _recid; /** * Comparator used to index entries. */ protected Comparator _comparator; /** * Serializer used to serialize index keys (optional) */ protected Serializer _keySerializer; /** * Serializer used to serialize index values (optional) */ protected Serializer _valueSerializer; /** * Height of the B+Tree. This is the number of BPages you have to traverse * to get to a leaf BPage, starting from the root. */ private int _height; /** * Recid of the root BPage */ private transient long _root; /** * Number of entries in each BPage. */ protected int _pageSize; /** * Total number of entries in the BTree */ protected int _entries; /** * Serializer used for BPages of this tree */ private transient BPage _bpageSerializer; /** * No-argument constructor used by serialization. */ public BTree() { // empty } /** * Create a new persistent BTree, with 16 entries per node. * * @param recman Record manager used for persistence. * @param comparator Comparator used to order index entries */ public static BTree createInstance( RecordManager recman, Comparator comparator ) throws IOException { return createInstance( recman, comparator, null, null, DEFAULT_SIZE ); } /** * Create a new persistent BTree, with 16 entries per node. * * @param recman Record manager used for persistence. * @param keySerializer Serializer used to serialize index keys (optional) * @param valueSerializer Serializer used to serialize index values (optional) * @param comparator Comparator used to order index entries */ public static BTree createInstance( RecordManager recman, Comparator comparator, Serializer keySerializer, Serializer valueSerializer ) throws IOException { return createInstance( recman, comparator, keySerializer, valueSerializer, DEFAULT_SIZE ); } /** * Create a new persistent BTree with the given number of entries per node. * * @param recman Record manager used for persistence. * @param comparator Comparator used to order index entries * @param keySerializer Serializer used to serialize index keys (optional) * @param valueSerializer Serializer used to serialize index values (optional) * @param pageSize Number of entries per page (must be even). */ public static BTree createInstance( RecordManager recman, Comparator comparator, Serializer keySerializer, Serializer valueSerializer, int pageSize ) throws IOException { BTree btree; if ( recman == null ) { throw new IllegalArgumentException( "Argument 'recman' is null" ); } if ( comparator == null ) { throw new IllegalArgumentException( "Argument 'comparator' is null" ); } if ( ! ( comparator instanceof Serializable ) ) { throw new IllegalArgumentException( "Argument 'comparator' must be serializable" ); } if ( keySerializer != null && ! ( keySerializer instanceof Serializable ) ) { throw new IllegalArgumentException( "Argument 'keySerializer' must be serializable" ); } if ( valueSerializer != null && ! ( valueSerializer instanceof Serializable ) ) { throw new IllegalArgumentException( "Argument 'valueSerializer' must be serializable" ); } // make sure there's an even number of entries per BPage if ( ( pageSize & 1 ) != 0 ) { throw new IllegalArgumentException( "Argument 'pageSize' must be even" ); } btree = new BTree(); btree._recman = recman; btree._comparator = comparator; btree._keySerializer = keySerializer; btree._valueSerializer = valueSerializer; btree._pageSize = pageSize; btree._bpageSerializer = new BPage(); btree._bpageSerializer._btree = btree; btree._recid = recman.insert( btree ); return btree; } /** * Load a persistent BTree. * * @param recman RecordManager used to store the persistent btree * @param recid Record id of the BTree */ public static BTree load( RecordManager recman, long recid ) throws IOException { BTree btree = (BTree) recman.fetch( recid ); btree._recid = recid; btree._recman = recman; btree._bpageSerializer = new BPage(); btree._bpageSerializer._btree = btree; return btree; } /** * Insert an entry in the BTree. *

* The BTree cannot store duplicate entries. An existing entry can be * replaced using the replace flag. If an entry with the * same key already exists in the BTree, its value is returned. * * @param key Insert key * @param value Insert value * @param replace Set to true to replace an existing key-value pair. * @return Existing value, if any. */ public synchronized Object insert( Object key, Object value, boolean replace ) throws IOException { if ( key == null ) { throw new IllegalArgumentException( "Argument 'key' is null" ); } if ( value == null ) { throw new IllegalArgumentException( "Argument 'value' is null" ); } BPage rootPage = getRoot(); if ( rootPage == null ) { // BTree is currently empty, create a new root BPage if (DEBUG) { System.out.println( "BTree.insert() new root BPage" ); } rootPage = new BPage( this, key, value ); _root = rootPage._recid; _height = 1; _entries = 1; _recman.update( _recid, this ); return null; } else { BPage.InsertResult insert = rootPage.insert( _height, key, value, replace ); boolean dirty = false; if ( insert._overflow != null ) { // current root page overflowed, we replace with a new root page if ( DEBUG ) { System.out.println( "BTree.insert() replace root BPage due to overflow" ); } rootPage = new BPage( this, rootPage, insert._overflow ); _root = rootPage._recid; _height += 1; dirty = true; } if ( insert._existing == null ) { _entries++; dirty = true; } if ( dirty ) { _recman.update( _recid, this ); } // insert might have returned an existing value return insert._existing; } } /** * Remove an entry with the given key from the BTree. * * @param key Removal key * @return Value associated with the key, or null if no entry with given * key existed in the BTree. */ public synchronized Object remove( Object key ) throws IOException { if ( key == null ) { throw new IllegalArgumentException( "Argument 'key' is null" ); } BPage rootPage = getRoot(); if ( rootPage == null ) { return null; } boolean dirty = false; BPage.RemoveResult remove = rootPage.remove( _height, key ); if ( remove._underflow && rootPage.isEmpty() ) { _height -= 1; dirty = true; // TODO: check contract for BPages to be removed from recman. if ( _height == 0 ) { _root = 0; } else { _root = rootPage.childBPage( _pageSize-1 )._recid; } } if ( remove._value != null ) { _entries--; dirty = true; } if ( dirty ) { _recman.update( _recid, this ); } return remove._value; } /** * Find the value associated with the given key. * * @param key Lookup key. * @return Value associated with the key, or null if not found. */ public synchronized Object find( Object key ) throws IOException { if ( key == null ) { throw new IllegalArgumentException( "Argument 'key' is null" ); } BPage rootPage = getRoot(); if ( rootPage == null ) { return null; } Tuple tuple = new Tuple( null, null ); TupleBrowser browser = rootPage.find( _height, key ); if ( browser.getNext( tuple ) ) { // find returns the matching key or the next ordered key, so we must // check if we have an exact match if ( _comparator.compare( key, tuple.getKey() ) != 0 ) { return null; } else { return tuple.getValue(); } } else { return null; } } /** * Find the value associated with the given key, or the entry immediately * following this key in the ordered BTree. * * @param key Lookup key. * @return Value associated with the key, or a greater entry, or null if no * greater entry was found. */ public synchronized Tuple findGreaterOrEqual( Object key ) throws IOException { Tuple tuple; TupleBrowser browser; if ( key == null ) { // there can't be a key greater than or equal to "null" // because null is considered an infinite key. return null; } tuple = new Tuple( null, null ); browser = browse( key ); if ( browser.getNext( tuple ) ) { return tuple; } else { return null; } } /** * Get a browser initially positioned at the beginning of the BTree. *

* WARNING:  If you make structural modifications to the BTree during * browsing, you will get inconsistent browing results. * * * @return Browser positionned at the beginning of the BTree. */ public synchronized TupleBrowser browse() throws IOException { BPage rootPage = getRoot(); if ( rootPage == null ) { return EmptyBrowser.INSTANCE; } TupleBrowser browser = rootPage.findFirst(); return browser; } /** * Get a browser initially positioned just before the given key. *

* WARNING:  If you make structural modifications to the BTree during * browsing, you will get inconsistent browing results. * * * @param key Key used to position the browser. If null, the browser * will be positionned after the last entry of the BTree. * (Null is considered to be an "infinite" key) * @return Browser positionned just before the given key. */ public synchronized TupleBrowser browse( Object key ) throws IOException { BPage rootPage = getRoot(); if ( rootPage == null ) { return EmptyBrowser.INSTANCE; } TupleBrowser browser = rootPage.find( _height, key ); return browser; } /** * Return the number of entries (size) of the BTree. */ public synchronized int size() { return _entries; } /** * Return the persistent record identifier of the BTree. */ public long getRecid() { return _recid; } /** * Return the root BPage, or null if it doesn't exist. */ private BPage getRoot() throws IOException { if ( _root == 0 ) { return null; } BPage root = (BPage) _recman.fetch( _root, _bpageSerializer ); root._recid = _root; root._btree = this; return root; } /** * Implement Externalizable interface. */ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException { _comparator = (Comparator) in.readObject(); _keySerializer = (Serializer) in.readObject(); _valueSerializer = (Serializer) in.readObject(); _height = in.readInt(); _root = in.readLong(); _pageSize = in.readInt(); _entries = in.readInt(); } /** * Implement Externalizable interface. */ public void writeExternal( ObjectOutput out ) throws IOException { out.writeObject( _comparator ); out.writeObject( _keySerializer ); out.writeObject( _valueSerializer ); out.writeInt( _height ); out.writeLong( _root ); out.writeInt( _pageSize ); out.writeInt( _entries ); } /* public void assert() throws IOException { BPage root = getRoot(); if ( root != null ) { root.assertRecursive( _height ); } } */ /* public void dump() throws IOException { BPage root = getRoot(); if ( root != null ) { root.dumpRecursive( _height, 0 ); } } */ /** PRIVATE INNER CLASS * Browser returning no element. */ static class EmptyBrowser extends TupleBrowser { static TupleBrowser INSTANCE = new EmptyBrowser(); public boolean getNext( Tuple tuple ) { return false; } public boolean getPrevious( Tuple tuple ) { return false; } } } libjdbm-java-1.0.orig/src/main/jdbm/btree/package.html0000644000175000017500000000057410276576000022613 0ustar twernertwerner

B+Tree (scalable persistent tree) data structure implementation.

Version:
$Revision: 1.1 $ $Date: 2001/05/19 16:01:32 $
Author:
Alex Boisvert
libjdbm-java-1.0.orig/src/main/jdbm/helper/0000775000175000017500000000000010276576000020504 5ustar twernertwernerlibjdbm-java-1.0.orig/src/main/jdbm/helper/ByteArrayComparator.java0000644000175000017500000001061310276576000025300 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.util.Comparator; import java.io.Serializable; /** * Comparator for byte arrays. * * @author Alex Boisvert * @version $Id: ByteArrayComparator.java,v 1.4 2002/05/31 06:33:20 boisvert Exp $ */ public final class ByteArrayComparator implements Comparator, Serializable { /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Compare two objects. * * @param obj1 First object * @param obj2 Second object * @return a positive integer if obj1 > obj2, 0 if obj1 == obj2, * and a negative integer if obj1 < obj2 */ public int compare( Object obj1, Object obj2 ) { if ( obj1 == null ) { throw new IllegalArgumentException( "Argument 'obj1' is null" ); } if ( obj2 == null ) { throw new IllegalArgumentException( "Argument 'obj2' is null" ); } return compareByteArray( (byte[]) obj1, (byte[]) obj2 ); } /** * Compare two byte arrays. */ public static int compareByteArray( byte[] thisKey, byte[] otherKey ) { int len = Math.min( thisKey.length, otherKey.length ); // compare the byte arrays for ( int i=0; i= 0 ) { if ( otherKey[i] >= 0 ) { // both positive if ( thisKey[i] < otherKey[i] ) { return -1; } else if ( thisKey[i] > otherKey[i] ) { return 1; } } else { // otherKey is negative => greater (because MSB is 1) return -1; } } else { if ( otherKey[i] >= 0 ) { // thisKey is negative => greater (because MSB is 1) return 1; } else { // both negative if ( thisKey[i] < otherKey[i] ) { return -1; } else if ( thisKey[i] > otherKey[i] ) { return 1; } } } } if ( thisKey.length == otherKey.length) { return 0; } if ( thisKey.length < otherKey.length ) { return -1; } return 1; } } libjdbm-java-1.0.orig/src/main/jdbm/helper/ByteArraySerializer.java0000644000175000017500000000646310276576000025312 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.IOException; /** * Serializer for byte arrays -- simple returns the byte array itself. No actual * serialization is performed. * * @author Alex Boisvert * @version $Id: ByteArraySerializer.java,v 1.1 2003/03/21 02:48:42 boisvert Exp $ */ public final class ByteArraySerializer implements Serializer { /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Static instance. */ public static final ByteArraySerializer INSTANCE = new ByteArraySerializer(); /** * Serialize the content of an object into a byte array. * * @param obj Object to serialize * @return a byte array representing the object's state * */ public byte[] serialize( Object obj ) throws IOException { return (byte[]) obj; } /** * Deserialize the content of an object from a byte array. * * @param serialized Byte array representation of the object * @return deserialized object * */ public Object deserialize( byte[] serialized ) throws IOException { return serialized; } } libjdbm-java-1.0.orig/src/main/jdbm/helper/CacheEvictionException.java0000644000175000017500000000523510276576000025735 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: CacheEvictionException.java,v 1.4 2003/10/21 15:43:20 boisvert Exp $ */ package jdbm.helper; /** * Exception that occurs during eviction of an object in the cache. * * @author Alex Boisvert * @version $Id: CacheEvictionException.java,v 1.4 2003/10/21 15:43:20 boisvert Exp $ */ public class CacheEvictionException extends Exception { /** * Nested exception -- the original exception that occured, if any. */ protected Exception _nested; public CacheEvictionException( Exception nested ) { _nested = nested; } public Exception getNestedException() { return _nested; } } libjdbm-java-1.0.orig/src/main/jdbm/helper/CachePolicy.java0000644000175000017500000001247110276576000023535 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: CachePolicy.java,v 1.5 2003/11/01 13:25:02 dranatunga Exp $ */ package jdbm.helper; import java.util.Enumeration; /** * CachePolicity is an abstraction for different cache policies. * (ie. MRU, time-based, soft-refs, ...) * * @author Alex Boisvert * @author Dilum Ranatunga * @version $Id: CachePolicy.java,v 1.5 2003/11/01 13:25:02 dranatunga Exp $ */ public interface CachePolicy { /** * Place an object in the cache. If the cache does not currently contain * an object for the key specified, this mapping is added. If an object * currently exists under the specified key, the current object is * replaced with the new object. *

* If the changes to the cache cause the eviction of any objects * stored under other key(s), events corresponding to * the evictions are fired for each object. If an event listener is * unable to handle the eviction, and throws a cache eviction exception, * that exception is propagated to the caller. If such an exception is * thrown, the cache itself should be left as it was before the * put() operation was invoked: the the object whose * eviction failed is still in the cache, and the new insertion or * modification is reverted. * * @param key key for the cached object * @param value the cached object * @throws CacheEvictionException propagated if, while evicting objects * to make room for new object, an eviction listener encountered * this problem. */ public void put( Object key, Object value ) throws CacheEvictionException; /** * Obtain the object stored under the key specified. * * @param key key the object was cached under * @return the object if it is still in the cache, null otherwise. */ public Object get( Object key ); /** * Remove the object stored under the key specified. Note that since * eviction notices are only fired when objects under different * keys are evicted, no event is fired for any object stored * under this key (see {@link #put(Object, Object) put( )}). * * @param key key the object was stored in the cache under. */ public void remove( Object key ); /** * Remove all objects from the cache. Consistent with * {@link #remove(Object) remove( )}, no eviction notices are fired. */ public void removeAll(); /** * Enumerate through the objects currently in the cache. */ public Enumeration elements(); /** * Add a listener to this cache policy. *

* If this cache policy already contains a listener that is equal to * the one being added, this call has no effect. * * @param listener the (non-null) listener to add to this policy * @throws IllegalArgumentException if listener is null. */ public void addListener( CachePolicyListener listener ) throws IllegalArgumentException; /** * Remove a listener from this cache policy. The listener is found * using object equality, not identity. * * @param listener the listener to remove from this policy */ public void removeListener( CachePolicyListener listener ); } libjdbm-java-1.0.orig/src/main/jdbm/helper/CachePolicyListener.java0000644000175000017500000000627410276576000025247 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: CachePolicyListener.java,v 1.3 2003/11/01 13:25:41 dranatunga Exp $ */ package jdbm.helper; /** * Callback interface between {@link CachePolicy} and a Cache implementation * to notify about cached object eviction. *

* Note that CachePolicy implementations typically use * object equality when removing listeners, so concrete * implementations of this interface should also pay attention to * their {@link Object#equals(Object)} and {@link Object#hashCode()} * methods. * * @author Alex Boisvert * @version $Id: CachePolicyListener.java,v 1.3 2003/11/01 13:25:41 dranatunga Exp $ */ public interface CachePolicyListener { /** * Notification that the cache this listener is attached to is evicting * the object indicated. * * @param obj object being evited from cache * @throws CacheEvictionException if this listener encountered problems * while preparing for the specified object's eviction. For example, * a listener may try to persist the object to disk, and encounter * an IOException. */ public void cacheObjectEvicted(Object obj) throws CacheEvictionException; } libjdbm-java-1.0.orig/src/main/jdbm/helper/Conversion.java0000644000175000017500000001562410276576000023502 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; /** * Miscelaneous conversion utility methods. * * @author Alex Boisvert * @version $Id: Conversion.java,v 1.3 2002/05/31 06:33:20 boisvert Exp $ */ public class Conversion { /** * Convert a string into a byte array. */ public static byte[] convertToByteArray( String s ) { try { // see the following page for character encoding // http://java.sun.com/products/jdk/1.1/docs/guide/intl/encoding.doc.html return s.getBytes( "UTF8" ); } catch ( java.io.UnsupportedEncodingException uee ) { uee.printStackTrace(); throw new Error( "Platform doesn't support UTF8 encoding" ); } } /** * Convert a byte into a byte array. */ public static byte[] convertToByteArray( byte n ) { n = (byte)( n ^ ( (byte) 0x80 ) ); // flip MSB because "byte" is signed return new byte[] { n }; } /** * Convert a short into a byte array. */ public static byte[] convertToByteArray( short n ) { n = (short) ( n ^ ( (short) 0x8000 ) ); // flip MSB because "short" is signed byte[] key = new byte[ 2 ]; pack2( key, 0, n ); return key; } /** * Convert an int into a byte array. */ public static byte[] convertToByteArray( int n ) { n = (n ^ 0x80000000); // flip MSB because "int" is signed byte[] key = new byte[4]; pack4(key, 0, n); return key; } /** * Convert a long into a byte array. */ public static byte[] convertToByteArray( long n ) { n = (n ^ 0x8000000000000000L); // flip MSB because "long" is signed byte[] key = new byte[8]; pack8( key, 0, n ); return key; } /** * Convert a byte array (encoded as UTF-8) into a String */ public static String convertToString( byte[] buf ) { try { // see the following page for character encoding // http://java.sun.com/products/jdk/1.1/docs/guide/intl/encoding.doc.html return new String( buf, "UTF8" ); } catch ( java.io.UnsupportedEncodingException uee ) { uee.printStackTrace(); throw new Error( "Platform doesn't support UTF8 encoding" ); } } /** * Convert a byte array into an integer (signed 32-bit) value. */ public static int convertToInt( byte[] buf ) { int value = unpack4( buf, 0 ); value = ( value ^ 0x80000000 ); // flip MSB because "int" is signed return value; } /** * Convert a byte array into a long (signed 64-bit) value. */ public static long convertToLong( byte[] buf ) { long value = ( (long) unpack4( buf, 0 ) << 32 ) + ( unpack4( buf, 4 ) & 0xFFFFFFFFL ); value = ( value ^ 0x8000000000000000L ); // flip MSB because "long" is signed return value; } static int unpack4( byte[] buf, int offset ) { int value = ( buf[ offset ] << 24 ) | ( ( buf[ offset+1 ] << 16 ) & 0x00FF0000 ) | ( ( buf[ offset+2 ] << 8 ) & 0x0000FF00 ) | ( ( buf[ offset+3 ] << 0 ) & 0x000000FF ); return value; } static final void pack2( byte[] data, int offs, int val ) { data[offs++] = (byte) ( val >> 8 ); data[offs++] = (byte) val; } static final void pack4( byte[] data, int offs, int val ) { data[offs++] = (byte) ( val >> 24 ); data[offs++] = (byte) ( val >> 16 ); data[offs++] = (byte) ( val >> 8 ); data[offs++] = (byte) val; } static final void pack8( byte[] data, int offs, long val ) { pack4( data, 0, (int) ( val >> 32 ) ); pack4( data, 4, (int) val ); } /** * Test static methods */ public static void main( String[] args ) { byte[] buf; buf = convertToByteArray( (int) 5 ); System.out.println( "int value of 5 is: " + convertToInt( buf ) ); buf = convertToByteArray( (int) -1 ); System.out.println( "int value of -1 is: " + convertToInt( buf ) ); buf = convertToByteArray( (int) 22111000 ); System.out.println( "int value of 22111000 is: " + convertToInt( buf ) ); buf = convertToByteArray( (long) 5L ); System.out.println( "long value of 5 is: " + convertToLong( buf ) ); buf = convertToByteArray( (long) -1L ); System.out.println( "long value of -1 is: " + convertToLong( buf ) ); buf = convertToByteArray( (long) 1112223334445556667L ); System.out.println( "long value of 1112223334445556667 is: " + convertToLong( buf ) ); } } libjdbm-java-1.0.orig/src/main/jdbm/helper/DefaultSerializer.java0000644000175000017500000000657210276576000024775 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.IOException; /** * Default java serializer. * * @author Alex Boisvert * @version $Id: DefaultSerializer.java,v 1.2 2003/09/21 15:47:00 boisvert Exp $ */ public class DefaultSerializer implements Serializer { public static final DefaultSerializer INSTANCE = new DefaultSerializer(); /** * Construct a DefaultSerializer. */ public DefaultSerializer() { // no op } /** * Serialize the content of an object into a byte array. * * @param obj Object to serialize * @return a byte array representing the object's state */ public byte[] serialize( Object obj ) throws IOException { return Serialization.serialize( obj ); } /** * Deserialize the content of an object from a byte array. * * @param serialized Byte array representation of the object * @return deserialized object */ public Object deserialize( byte[] serialized ) throws IOException { try { return Serialization.deserialize( serialized ); } catch ( ClassNotFoundException except ) { throw new WrappedRuntimeException( except ); } } } libjdbm-java-1.0.orig/src/main/jdbm/helper/FastIterator.java0000644000175000017500000000501710276576000023757 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FastIterator.java,v 1.2 2003/10/21 15:43:58 boisvert Exp $ */ package jdbm.helper; /** * Fast and simple iterator. * * @version $Revision: 1.2 $ * @author Alex Boisvert */ public abstract class FastIterator { /** * Returns the next element in the interation. * * @return the next element in the iteration, or null if no more element. */ public abstract Object next() throws IterationException; } libjdbm-java-1.0.orig/src/main/jdbm/helper/IntegerComparator.java0000644000175000017500000000657310276576000025005 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.Serializable; import java.util.Comparator; /** * Comparator for Integer objects. * * @author Christof Dallermassl * @version $Id: IntegerComparator.java,v 1.2 2002/05/31 06:33:20 boisvert Exp $ */ public final class IntegerComparator implements Comparator, Serializable { /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Compare two objects. * * @param obj1 First object * @param obj2 Second object * @return a positive integer if obj1 > obj2, 0 if obj1 == obj2, * and a negative integer if obj1 < obj2 */ public int compare( Object obj1, Object obj2 ) { if ( obj1 == obj2 ) { return 0; } if ( obj1 == null ) { throw new IllegalArgumentException( "Argument 'obj1' is null" ); } if ( obj2 == null ) { throw new IllegalArgumentException( "Argument 'obj2' is null" ); } // complicated to avoid usage of Integer.compareTo, as this // method is Java 1.2 only! int int1 = ( (Integer) obj1 ).intValue(); int int2 = ( (Integer) obj2 ).intValue(); if ( int1 == int2 ) { return 0; } if ( int1 < int2 ) { return -1; } else { return 1; } } } libjdbm-java-1.0.orig/src/main/jdbm/helper/IntegerSerializer.java0000644000175000017500000000654010276576000025001 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.IOException; /** * Optimized serializer for integers. * * @author Alex Boisvert * @version $Id: IntegerSerializer.java,v 1.2 2003/09/21 15:47:00 boisvert Exp $ */ public class IntegerSerializer implements Serializer { public static final IntegerSerializer INSTANCE = new IntegerSerializer(); /** * Construct an IntegerSerializer. */ public IntegerSerializer() { // no op } /** * Serialize the content of an object into a byte array. * * @param obj Object to serialize * @return a byte array representing the object's state */ public byte[] serialize( Object obj ) throws IOException { Integer number = (Integer) obj; return Conversion.convertToByteArray( number.intValue() ); } /** * Deserialize the content of an object from a byte array. * * @param serialized Byte array representation of the object * @return deserialized object */ public Object deserialize( byte[] serialized ) throws IOException { int number = Conversion.convertToInt( serialized ); return new Integer( number ); } } libjdbm-java-1.0.orig/src/main/jdbm/helper/IterationException.java0000644000175000017500000000620710276576000025167 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: IterationException.java,v 1.2 2003/09/21 15:47:00 boisvert Exp $ */ package jdbm.helper; /** * Iteration exception. * * @author Alex Boisvert * @version $Revision: 1.2 $ */ public class IterationException extends WrappedRuntimeException { /** * Construct a new iteration exception wrapping an underlying exception * and providing a message. * * @param message The exception message * @param except The underlying exception */ public IterationException( String message, Exception except ) { super( message, except ); } /** * Construct a new iteration exception with a message. * * @param message The exception message */ public IterationException( String message ) { super( message, null ); } /** * Construct a new iteration exception wrapping an underlying exception. * * @param except The underlying exception */ public IterationException( Exception except ) { super( except ); } } libjdbm-java-1.0.orig/src/main/jdbm/helper/LongComparator.java0000644000175000017500000000631010276576000024274 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.Serializable; import java.util.Comparator; /** * Comparator for java.lang.Long objects. * * @author Alex Boisvert * @version $Id: LongComparator.java,v 1.4 2002/05/31 06:33:20 boisvert Exp $ */ public final class LongComparator implements Comparator, Serializable { /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Compare two objects. * * @param obj1 First object * @param obj2 Second object * @return a positive integer if obj1 > obj2, 0 if obj1 == obj2, * and a negative integer if obj1 < obj2 */ public int compare( Object obj1, Object obj2 ) { if ( obj1 == null ) { throw new IllegalArgumentException( "Argument 'obj1' is null" ); } if ( obj2 == null ) { throw new IllegalArgumentException( "Argument 'obj2' is null" ); } long l1 = ( (Long) obj1 ).longValue(); long l2 = ( (Long) obj2 ).longValue(); if ( l1 > l2 ) { return 1; } else if ( l1 == l2 ) { return 0; } else { return -1; } } } libjdbm-java-1.0.orig/src/main/jdbm/helper/LongSerializer.java0000644000175000017500000000651510276576000024305 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.IOException; /** * Optimized serializer for long integers. * * @author Alex Boisvert * @version $Id: LongSerializer.java,v 1.2 2003/09/21 15:47:00 boisvert Exp $ */ public class LongSerializer implements Serializer { public static final LongSerializer INSTANCE = new LongSerializer(); /** * Construct a LongSerializer. */ public LongSerializer() { // no op } /** * Serialize the content of an object into a byte array. * * @param obj Object to serialize * @return a byte array representing the object's state */ public byte[] serialize( Object obj ) throws IOException { Long number = (Long) obj; return Conversion.convertToByteArray( number.longValue() ); } /** * Deserialize the content of an object from a byte array. * * @param serialized Byte array representation of the object * @return deserialized object */ public Object deserialize( byte[] serialized ) throws IOException { long number = Conversion.convertToLong( serialized ); return new Long( number ); } } libjdbm-java-1.0.orig/src/main/jdbm/helper/MRU.java0000644000175000017500000002073410276576000022016 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: MRU.java,v 1.8 2005/06/25 23:12:31 doomdark Exp $ */ package jdbm.helper; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; /** * MRU - Most Recently Used cache policy. * * Methods are *not* synchronized, so no concurrent access is allowed. * * @author Alex Boisvert * @version $Id: MRU.java,v 1.8 2005/06/25 23:12:31 doomdark Exp $ */ public class MRU implements CachePolicy { /** Cached object hashtable */ Hashtable _hash = new Hashtable(); /** * Maximum number of objects in the cache. */ int _max; /** * Beginning of linked-list of cache elements. First entry is element * which has been used least recently. */ CacheEntry _first; /** * End of linked-list of cache elements. Last entry is element * which has been used most recently. */ CacheEntry _last; /** * Cache eviction listeners */ Vector listeners = new Vector(); /** * Construct an MRU with a given maximum number of objects. */ public MRU(int max) { if (max <= 0) { throw new IllegalArgumentException("MRU cache must contain at least one entry"); } _max = max; } /** * Place an object in the cache. */ public void put(Object key, Object value) throws CacheEvictionException { CacheEntry entry = (CacheEntry)_hash.get(key); if (entry != null) { entry.setValue(value); touchEntry(entry); } else { if (_hash.size() == _max) { // purge and recycle entry entry = purgeEntry(); entry.setKey(key); entry.setValue(value); } else { entry = new CacheEntry(key, value); } addEntry(entry); _hash.put(entry.getKey(), entry); } } /** * Obtain an object in the cache */ public Object get(Object key) { CacheEntry entry = (CacheEntry)_hash.get(key); if (entry != null) { touchEntry(entry); return entry.getValue(); } else { return null; } } /** * Remove an object from the cache */ public void remove(Object key) { CacheEntry entry = (CacheEntry)_hash.get(key); if (entry != null) { removeEntry(entry); _hash.remove(entry.getKey()); } } /** * Remove all objects from the cache */ public void removeAll() { _hash = new Hashtable(); _first = null; _last = null; } /** * Enumerate elements' values in the cache */ public Enumeration elements() { return new MRUEnumeration(_hash.elements()); } /** * Add a listener to this cache policy * * @param listener Listener to add to this policy */ public void addListener(CachePolicyListener listener) { if (listener == null) { throw new IllegalArgumentException("Cannot add null listener."); } if ( ! listeners.contains(listener)) { listeners.addElement(listener); } } /** * Remove a listener from this cache policy * * @param listener Listener to remove from this policy */ public void removeListener(CachePolicyListener listener) { listeners.removeElement(listener); } /** * Add a CacheEntry. Entry goes at the end of the list. */ protected void addEntry(CacheEntry entry) { if (_first == null) { _first = entry; _last = entry; } else { _last.setNext(entry); entry.setPrevious(_last); _last = entry; } } /** * Remove a CacheEntry from linked list */ protected void removeEntry(CacheEntry entry) { if (entry == _first) { _first = entry.getNext(); } if (_last == entry) { _last = entry.getPrevious(); } CacheEntry previous = entry.getPrevious(); CacheEntry next = entry.getNext(); if (previous != null) { previous.setNext(next); } if (next != null) { next.setPrevious(previous); } entry.setPrevious(null); entry.setNext(null); } /** * Place entry at the end of linked list -- Most Recently Used */ protected void touchEntry(CacheEntry entry) { if (_last == entry) { return; } removeEntry(entry); addEntry(entry); } /** * Purge least recently used object from the cache * * @return recyclable CacheEntry */ protected CacheEntry purgeEntry() throws CacheEvictionException { CacheEntry entry = _first; // Notify policy listeners first. if any of them throw an // eviction exception, then the internal data structure // remains untouched. CachePolicyListener listener; for (int i=0; iAlex Boisvert * @version $Id: ObjectBAComparator.java,v 1.1 2002/05/31 06:33:20 boisvert Exp $ */ public final class ObjectBAComparator implements Comparator, Serializable { /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Wrapped comparator. */ private Comparator _comparator; /** * Construct an ObjectByteArrayComparator which wraps an Object Comparator. * * @param comparator Object comparator. */ public ObjectBAComparator( Comparator comparator ) { if ( comparator == null ) { throw new IllegalArgumentException( "Argument 'comparator' is null" ); } _comparator = comparator; } /** * Compare two objects. * * @param obj1 First object * @param obj2 Second object * @return 1 if obj1 > obj2, 0 if obj1 == obj2, -1 if obj1 < obj2 */ public int compare( Object obj1, Object obj2 ) { if ( obj1 == null ) { throw new IllegalArgumentException( "Argument 'obj1' is null" ); } if ( obj2 == null ) { throw new IllegalArgumentException( "Argument 'obj2' is null" ); } try { obj1 = Serialization.deserialize( (byte[]) obj1 ); obj2 = Serialization.deserialize( (byte[]) obj2 ); return _comparator.compare( obj1, obj2 ); } catch ( IOException except ) { throw new WrappedRuntimeException( except ); } catch ( ClassNotFoundException except ) { throw new WrappedRuntimeException( except ); } } /** * Compare two byte arrays. */ public static int compareByteArray( byte[] thisKey, byte[] otherKey ) { int len = Math.min( thisKey.length, otherKey.length ); // compare the byte arrays for ( int i=0; i= 0 ) { if ( otherKey[i] >= 0 ) { // both positive if ( thisKey[i] < otherKey[i] ) { return -1; } else if ( thisKey[i] > otherKey[i] ) { return 1; } } else { // otherKey is negative => greater (because MSB is 1) return -1; } } else { if ( otherKey[i] >= 0 ) { // thisKey is negative => greater (because MSB is 1) return 1; } else { // both negative if ( thisKey[i] < otherKey[i] ) { return -1; } else if ( thisKey[i] > otherKey[i] ) { return 1; } } } } if ( thisKey.length == otherKey.length) { return 0; } if ( thisKey.length < otherKey.length ) { return -1; } return 1; } } libjdbm-java-1.0.orig/src/main/jdbm/helper/package.html0000644000175000017500000000055010276576000022763 0ustar twernertwerner

Miscelaneous utility classes and interfaces.

Version:
$Revision: 1.1 $ $Date: 2001/05/19 16:01:33 $
Author:
Alex Boisvert
libjdbm-java-1.0.orig/src/main/jdbm/helper/Serialization.java0000644000175000017500000000640610276576000024170 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * Serialization-related utility methods. * * @author Alex Boisvert * @version $Id: Serialization.java,v 1.1 2002/05/31 06:33:20 boisvert Exp $ */ public final class Serialization { /** * Serialize the object into a byte array. */ public static byte[] serialize( Object obj ) throws IOException { ByteArrayOutputStream baos; ObjectOutputStream oos; baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream( baos ); oos.writeObject( obj ); oos.close(); return baos.toByteArray(); } /** * Deserialize an object from a byte array */ public static Object deserialize( byte[] buf ) throws ClassNotFoundException, IOException { ByteArrayInputStream bais; ObjectInputStream ois; bais = new ByteArrayInputStream( buf ); ois = new ObjectInputStream( bais ); return ois.readObject(); } } libjdbm-java-1.0.orig/src/main/jdbm/helper/Serializer.java0000644000175000017500000000573410276576000023467 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.IOException; import java.io.Serializable; /** * Interface used to provide a serialization mechanism other than a class' normal * serialization. * * @author Alex Boisvert * @version $Id: Serializer.java,v 1.1 2003/03/21 02:48:42 boisvert Exp $ */ public interface Serializer extends Serializable { /** * Serialize the content of an object into a byte array. * * @param obj Object to serialize * @return a byte array representing the object's state */ public byte[] serialize( Object obj ) throws IOException; /** * Deserialize the content of an object from a byte array. * * @param serialized Byte array representation of the object * @return deserialized object */ public Object deserialize( byte[] serialized ) throws IOException; } libjdbm-java-1.0.orig/src/main/jdbm/helper/SoftCache.java0000644000175000017500000002626710276576000023221 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id */ package jdbm.helper; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.Reference; import java.util.Enumeration; import java.util.Map; import java.util.HashMap; /** * Wraps a deterministic cache policy with a Level-2 cache based on * J2SE's {@link SoftReference soft references}. Soft references allow * this cache to keep references to objects until the memory they occupy * is required elsewhere. *

* Since the {@link CachePolicy} interface requires an event be fired * when an object is evicted, and the event contains the actual object, * this class cannot be a stand-alone implementation of * CachePolicy. This limitation arises because Java References * does not support notification before references are cleared; nor do * they support reaching soft referents. Therefore, this wrapper cache * aggressively notifies evictions: events are fired when the objects are * evicted from the internal cache. Consequently, the soft cache may return * a non-null object when get( ) is called, even if that * object was said to have been evicted. *

* The current implementation uses a hash structure for its internal key * to value mappings. *

* Note: this component's publicly exposed methods are not threadsafe; * potentially concurrent code should synchronize on the cache instance. * * @author Dilum Ranatunga * @version $Id: SoftCache.java,v 1.1 2003/11/01 13:29:27 dranatunga Exp $ */ public class SoftCache implements CachePolicy { private static final int INITIAL_CAPACITY = 128; private static final float DEFAULT_LOAD_FACTOR = 1.5f; private final ReferenceQueue _clearQueue = new ReferenceQueue(); private final CachePolicy _internal; private final Map _cacheMap; /** * Creates a soft-reference based L2 cache with a {@link MRU} cache as * the internal (L1) cache. The soft reference cache uses the * default load capacity of 1.5f, which is intended to sacrifice some * performance for space. This compromise is reasonable, since all * {@link #get(Object) get( )s} first try the L1 cache anyway. The * internal MRU is given a capacity of 128 elements. */ public SoftCache() { this(new MRU(INITIAL_CAPACITY)); } /** * Creates a soft-reference based L2 cache wrapping the specified * L1 cache. * * @param internal non null internal cache. * @throws NullPointerException if the internal cache is null. */ public SoftCache(CachePolicy internal) throws NullPointerException { this(DEFAULT_LOAD_FACTOR, internal); } /** * Creates a soft-reference based L2 cache wrapping the specified * L1 cache. This constructor is somewhat implementation-specific, * so users are encouraged to use {@link #SoftCache(CachePolicy)} * instead. * * @param loadFactor load factor that the soft cache's hash structure * should use. * @param internal non null internal cache. * @throws IllegalArgumentException if the load factor is nonpositive. * @throws NullPointerException if the internal cache is null. */ public SoftCache(float loadFactor, CachePolicy internal) throws IllegalArgumentException, NullPointerException { if (internal == null) { throw new NullPointerException("Internal cache cannot be null."); } _internal = internal; _cacheMap = new HashMap(INITIAL_CAPACITY, loadFactor); } /** * Adds the specified value to the cache under the specified key. Note * that the object is added to both this and the internal cache. * @param key the (non-null) key to store the object under * @param value the (non-null) object to place in the cache * @throws CacheEvictionException exception that the internal cache * would have experienced while evicting an object it currently * cached. */ public void put(Object key, Object value) throws CacheEvictionException { if (key == null) { throw new IllegalArgumentException("key cannot be null."); } else if (value == null) { throw new IllegalArgumentException("value cannot be null."); } _internal.put(key, value); removeClearedEntries(); _cacheMap.put(key, new Entry(key, value, _clearQueue)); } /** * Gets the object cached under the specified key. *

* The cache is looked up in the following manner: *

    *
  1. The internal (L1) cache is checked. If the object is found, it is * returned.
  2. *
  3. This (L2) cache is checked. If the object is not found, then * the caller is informed that the object is inaccessible.
  4. *
  5. Since the object exists in L2, but not in L1, the object is * readded to L1 using {@link CachePolicy#put(Object, Object)}.
  6. *
  7. If the readding succeeds, the value is returned to caller.
  8. *
  9. If a cache eviction exception is encountered instead, we * remove the object from L2 and behave as if the object was * inaccessible.
  10. *
* @param key the key that the object was stored under. * @return the object stored under the key specified; null if the * object is not (nolonger) accessible via this cache. */ public Object get(Object key) { // first try the internal cache. Object value = _internal.get(key); if (value != null) { return value; } // poll and remove cleared references. removeClearedEntries(); Entry entry = (Entry)_cacheMap.get(key); if (entry == null) { // object is not in cache. return null; } value = entry.getValue(); if (value == null) { // object was in cache, but it was cleared. return null; } // we have the object. so we try to re-insert it into internal cache try { _internal.put(key, value); } catch (CacheEvictionException e) { // if the internal cache causes a fuss, we kick the object out. _cacheMap.remove(key); return null; } return value; } /** * Removes any object stored under the key specified. Note that the * object is removed from both this (L2) and the internal (L1) * cache. * @param key the key whose object should be removed */ public void remove(Object key) { _cacheMap.remove(key); _internal.remove(key); } /** * Removes all objects in this (L2) and its internal (L1) cache. */ public void removeAll() { _cacheMap.clear(); _internal.removeAll(); } /** * Gets all the objects stored by the internal (L1) cache. * @return an enumeration of objects in internal cache. */ public Enumeration elements() { return _internal.elements(); } /** * Adds the specified listener to this cache. Note that the events * fired by this correspond to the internal cache's events. * @param listener the (non-null) listener to add to this policy * @throws IllegalArgumentException if listener is null. */ public void addListener(CachePolicyListener listener) throws IllegalArgumentException { _internal.addListener(listener); } /** * Removes a listener that was added earlier. * @param listener the listener to remove. */ public void removeListener(CachePolicyListener listener) { _internal.removeListener(listener); } /** * Cleans the mapping structure of any obsolete entries. This is usually * called before insertions and lookups on the mapping structure. The * runtime of this is usually very small, but it can be as expensive as * n * log(n) if a large number of soft references were recently cleared. */ private final void removeClearedEntries() { for (Reference r = _clearQueue.poll(); r != null; r = _clearQueue.poll()) { Object key = ((Entry)r).getKey(); _cacheMap.remove(key); } } /** * Value objects we keep in the internal map. This contains the key in * addition to the value, because polling for cleared references * returns these instances, and having access to their corresponding * keys drastically improves the performance of removing the pair * from the map (see {@link SoftCache#removeClearedEntries()}.) */ private static class Entry extends SoftReference { private final Object _key; /** * Constructor that uses value as the soft * reference's referent. */ public Entry(Object key, Object value, ReferenceQueue queue) { super(value, queue); _key = key; } /** * Gets the key * @return the key associated with this value. */ final Object getKey() { return _key; } /** * Gets the value * @return the value; null if it is no longer accessible */ final Object getValue() { return this.get(); } } } libjdbm-java-1.0.orig/src/main/jdbm/helper/StringComparator.java0000644000175000017500000000605310276576000024647 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.Serializable; import java.util.Comparator; /** * Comparator for String objects. Delegates to String.compareTo(). * * @author Alex Boisvert * @version $Id: StringComparator.java,v 1.5 2005/06/25 23:12:31 doomdark Exp $ */ public final class StringComparator implements Comparator, Serializable { /** * Version id for serialization. */ final static long serialVersionUID = 1L; /** * Compare two objects. * * @param obj1 First object * @param obj2 Second object * @return a positive integer if obj1 > obj2, 0 if obj1 == obj2, * and a negative integer if obj1 < obj2 */ public int compare( Object obj1, Object obj2 ) { if ( obj1 == null ) { throw new IllegalArgumentException( "Argument 'obj1' is null" ); } if ( obj2 == null ) { throw new IllegalArgumentException( "Argument 'obj2' is null" ); } return ( (String) obj1 ).compareTo((String) obj2 ); } } libjdbm-java-1.0.orig/src/main/jdbm/helper/Tuple.java0000644000175000017500000000602110276576000022435 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; /** * Tuple consisting of a key-value pair. * * @author Alex Boisvert * @version $Id: Tuple.java,v 1.2 2001/05/19 14:02:00 boisvert Exp $ */ public final class Tuple { /** * Key */ private Object _key; /** * Value */ private Object _value; /** * Construct an empty Tuple. */ public Tuple() { // empty } /** * Construct a Tuple. * * @param key The key. * @param value The value. */ public Tuple( Object key, Object value ) { _key = key; _value = value; } /** * Get the key. */ public Object getKey() { return _key; } /** * Set the key. */ public void setKey( Object key ) { _key = key; } /** * Get the value. */ public Object getValue() { return _value; } /** * Set the value. */ public void setValue( Object value ) { _value = value; } } libjdbm-java-1.0.orig/src/main/jdbm/helper/TupleBrowser.java0000644000175000017500000000564710276576000024016 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.IOException; /** * Browser to traverse a collection of tuples. The browser allows for * forward and reverse order traversal. * * @author Alex Boisvert * @version $Id: TupleBrowser.java,v 1.2 2001/05/19 14:02:00 boisvert Exp $ */ public abstract class TupleBrowser { /** * Get the next tuple. * * @param tuple Tuple into which values are copied. * @return True if values have been copied in tuple, or false if there is * no next tuple. */ public abstract boolean getNext( Tuple tuple ) throws IOException; /** * Get the previous tuple. * * @param tuple Tuple into which values are copied. * @return True if values have been copied in tuple, or false if there is * no previous tuple. */ public abstract boolean getPrevious( Tuple tuple ) throws IOException; } libjdbm-java-1.0.orig/src/main/jdbm/helper/WrappedRuntimeException.java0000644000175000017500000001116410276576000026175 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2001 by their associated contributors. * */ package jdbm.helper; import java.io.PrintStream; import java.io.PrintWriter; /** * A run-time exception that wraps another exception. The printed stack * trace will be that of the wrapped exception. * * @author Alex Boisvert * @version $Id: WrappedRuntimeException.java,v 1.1 2002/05/31 06:33:20 boisvert Exp $ */ public class WrappedRuntimeException extends RuntimeException { /** * The underlying exception. */ private final Exception _except; /** * Constructs a new runtime exception based on a checked exception. * * @param message The error message * @param except The checked exception */ public WrappedRuntimeException( String message, Exception except ) { super( message == null ? "No message available" : message ); if ( except instanceof WrappedRuntimeException && ( (WrappedRuntimeException) except )._except != null ) { _except = ( (WrappedRuntimeException) except )._except; } else { _except = except; } } /** * Constructs a new runtime exception based on a checked exception. * * @param except The checked exception */ public WrappedRuntimeException( Exception except ) { super( except == null || except.getMessage() == null ? "No message available" : except.getMessage() ); if ( except instanceof WrappedRuntimeException && ( (WrappedRuntimeException) except )._except != null ) { _except = ( (WrappedRuntimeException) except )._except; } else { _except = except; } } /** * Returns the exception wrapped by this runtime exception. * * @return The exception wrapped by this runtime exception */ public Exception getException() { return _except; } public void printStackTrace() { if ( _except == null ) { super.printStackTrace(); } else { _except.printStackTrace(); } } public void printStackTrace( PrintStream stream ) { if ( _except == null ) { super.printStackTrace( stream ); } else { _except.printStackTrace( stream ); } } public void printStackTrace( PrintWriter writer ) { if ( _except == null ) { super.printStackTrace( writer ); } else { _except.printStackTrace( writer ); } } } libjdbm-java-1.0.orig/src/main/jdbm/htree/0000775000175000017500000000000010276576000020334 5ustar twernertwernerlibjdbm-java-1.0.orig/src/main/jdbm/htree/HashBucket.java0000644000175000017500000002236410276576000023225 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.htree; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.ArrayList; /** * A bucket is a placeholder for multiple (key, value) pairs. Buckets * are used to store collisions (same hash value) at all levels of an * H*tree. * * There are two types of buckets: leaf and non-leaf. * * Non-leaf buckets are buckets which hold collisions which happen * when the H*tree is not fully expanded. Keys in a non-leaf buckets * can have different hash codes. Non-leaf buckets are limited to an * arbitrary size. When this limit is reached, the H*tree should create * a new Directory page and distribute keys of the non-leaf buckets into * the newly created Directory. * * A leaf bucket is a bucket which contains keys which all have * the same hashCode(). Leaf buckets stand at the * bottom of an H*tree because the hashing algorithm cannot further * discriminate between different keys based on their hash code. * * @author Alex Boisvert * @version $Id: HashBucket.java,v 1.2 2005/06/25 23:12:32 doomdark Exp $ */ final class HashBucket extends HashNode implements Externalizable { final static long serialVersionUID = 1L; /** * The maximum number of elements (key, value) a non-leaf bucket * can contain. */ public static final int OVERFLOW_SIZE = 8; /** * Depth of this bucket. */ private int _depth; /** * Keys in this bucket. Keys are ordered to match their respective * value in _values. */ private ArrayList _keys; /** * Values in this bucket. Values are ordered to match their respective * key in _keys. */ private ArrayList _values; /** * Public constructor for serialization. */ public HashBucket() { // empty } /** * Construct a bucket with a given depth level. Depth level is the * number of HashDirectory above this bucket. */ public HashBucket( int level ) { if ( level > HashDirectory.MAX_DEPTH+1 ) { throw new IllegalArgumentException( "Cannot create bucket with depth > MAX_DEPTH+1. " + "Depth=" + level ); } _depth = level; _keys = new ArrayList( OVERFLOW_SIZE ); _values = new ArrayList( OVERFLOW_SIZE ); } /** * Returns the number of elements contained in this bucket. */ public int getElementCount() { return _keys.size(); } /** * Returns whether or not this bucket is a "leaf bucket". */ public boolean isLeaf() { return ( _depth > HashDirectory.MAX_DEPTH ); } /** * Returns true if bucket can accept at least one more element. */ public boolean hasRoom() { if ( isLeaf() ) { return true; // leaf buckets are never full } else { // non-leaf bucket return ( _keys.size() < OVERFLOW_SIZE ); } } /** * Add an element (key, value) to this bucket. If an existing element * has the same key, it is replaced silently. * * @return Object which was previously associated with the given key * or null if no association existed. */ public Object addElement( Object key, Object value ) { int existing = _keys.indexOf(key); if ( existing != -1 ) { // replace existing element Object before = _values.get( existing ); _values.set( existing, value ); return before; } else { // add new (key, value) pair _keys.add( key ); _values.add( value ); return null; } } /** * Remove an element, given a specific key. * * @param key Key of the element to remove * * @return Removed element value, or null if not found */ public Object removeElement( Object key ) { int existing = _keys.indexOf(key); if ( existing != -1 ) { Object obj = _values.get( existing ); _keys.remove( existing ); _values.remove( existing ); return obj; } else { // not found return null; } } /** * Returns the value associated with a given key. If the given key * is not found in this bucket, returns null. */ public Object getValue( Object key ) { int existing = _keys.indexOf(key); if ( existing != -1 ) { return _values.get( existing ); } else { // key not found return null; } } /** * Obtain keys contained in this buckets. Keys are ordered to match * their values, which be be obtained by calling getValues(). * * As an optimization, the Vector returned is the instance member * of this class. Please don't modify outside the scope of this class. */ ArrayList getKeys() { return this._keys; } /** * Obtain values contained in this buckets. Values are ordered to match * their keys, which be be obtained by calling getKeys(). * * As an optimization, the Vector returned is the instance member * of this class. Please don't modify outside the scope of this class. */ ArrayList getValues() { return this._values; } /** * Implement Externalizable interface. */ public void writeExternal( ObjectOutput out ) throws IOException { out.writeInt( _depth ); int entries = _keys.size(); out.writeInt( entries ); // write keys for (int i=0; iAlex Boisvert * @version $Id: HashDirectory.java,v 1.5 2005/06/25 23:12:32 doomdark Exp $ */ final class HashDirectory extends HashNode implements Externalizable { static final long serialVersionUID = 1L; /** * Maximum number of children in a directory. * * (Must be a power of 2 -- if you update this value, you must also * update BIT_SIZE and MAX_DEPTH.) */ static final int MAX_CHILDREN = 256; /** * Number of significant bits per directory level. */ static final int BIT_SIZE = 8; // log2(256) = 8 /** * Maximum number of levels (zero-based) * * (4 * 8 bits = 32 bits, which is the size of an "int", and as * you know, hashcodes in Java are "ints") */ static final int MAX_DEPTH = 3; // 4 levels /** * Record ids of children pages. */ private long[] _children; /** * Depth of this directory page, zero-based */ private byte _depth; /** * PageManager used to persist changes in directory and buckets */ private transient RecordManager _recman; /** * This directory's record ID in the PageManager. (transient) */ private transient long _recid; /** * Public constructor used by serialization */ public HashDirectory() { // empty } /** * Construct a HashDirectory * * @param depth Depth of this directory page. */ HashDirectory(byte depth) { _depth = depth; _children = new long[MAX_CHILDREN]; } /** * Sets persistence context. This method must be called before any * persistence-related operation. * * @param recman RecordManager which stores this directory * @param recid Record id of this directory. */ void setPersistenceContext( RecordManager recman, long recid ) { this._recman = recman; this._recid = recid; } /** * Get the record identifier used to load this hashtable. */ long getRecid() { return _recid; } /** * Returns whether or not this directory is empty. A directory * is empty when it no longer contains buckets or sub-directories. */ boolean isEmpty() { for (int i=0; i<_children.length; i++) { if (_children[i] != 0) { return false; } } return true; } /** * Returns the value which is associated with the given key. Returns * null if there is not association for this key. * * @param key key whose associated value is to be returned */ Object get(Object key) throws IOException { int hash = hashCode( key ); long child_recid = _children[ hash ]; if ( child_recid == 0 ) { // not bucket/page --> not found return null; } else { HashNode node = (HashNode) _recman.fetch( child_recid ); // System.out.println("HashDirectory.get() child is : "+node); if ( node instanceof HashDirectory ) { // recurse into next directory level HashDirectory dir = (HashDirectory) node; dir.setPersistenceContext( _recman, child_recid ); return dir.get( key ); } else { // node is a bucket HashBucket bucket = (HashBucket) node; return bucket.getValue( key ); } } } /** * Associates the specified value with the specified key. * * @param key key with which the specified value is to be assocated. * @param value value to be associated with the specified key. * @return object which was previously associated with the given key, * or null if no association existed. */ Object put(Object key, Object value) throws IOException { if (value == null) { return remove(key); } int hash = hashCode(key); long child_recid = _children[hash]; if (child_recid == 0) { // no bucket/page here yet, let's create a bucket HashBucket bucket = new HashBucket(_depth+1); // insert (key,value) pair in bucket Object existing = bucket.addElement(key, value); long b_recid = _recman.insert(bucket); _children[hash] = b_recid; _recman.update(_recid, this); // System.out.println("Added: "+bucket); return existing; } else { HashNode node = (HashNode) _recman.fetch( child_recid ); if ( node instanceof HashDirectory ) { // recursive insert in next directory level HashDirectory dir = (HashDirectory) node; dir.setPersistenceContext( _recman, child_recid ); return dir.put( key, value ); } else { // node is a bucket HashBucket bucket = (HashBucket)node; if (bucket.hasRoom()) { Object existing = bucket.addElement(key, value); _recman.update(child_recid, bucket); // System.out.println("Added: "+bucket); return existing; } else { // overflow, so create a new directory if (_depth == MAX_DEPTH) { throw new RuntimeException( "Cannot create deeper directory. " + "Depth=" + _depth ); } HashDirectory dir = new HashDirectory( (byte) (_depth+1) ); long dir_recid = _recman.insert( dir ); dir.setPersistenceContext( _recman, dir_recid ); _children[hash] = dir_recid; _recman.update( _recid, this ); // discard overflown bucket _recman.delete( child_recid ); // migrate existing bucket elements ArrayList keys = bucket.getKeys(); ArrayList values = bucket.getValues(); int entries = keys.size(); for ( int i=0; inull if no association existed with given key. */ Object remove(Object key) throws IOException { int hash = hashCode(key); long child_recid = _children[hash]; if (child_recid == 0) { // not bucket/page --> not found return null; } else { HashNode node = (HashNode) _recman.fetch( child_recid ); // System.out.println("HashDirectory.remove() child is : "+node); if (node instanceof HashDirectory) { // recurse into next directory level HashDirectory dir = (HashDirectory)node; dir.setPersistenceContext( _recman, child_recid ); Object existing = dir.remove(key); if (existing != null) { if (dir.isEmpty()) { // delete empty directory _recman.delete(child_recid); _children[hash] = 0; _recman.update(_recid, this); } } return existing; } else { // node is a bucket HashBucket bucket = (HashBucket)node; Object existing = bucket.removeElement(key); if (existing != null) { if (bucket.getElementCount() >= 1) { _recman.update(child_recid, bucket); } else { // delete bucket, it's empty _recman.delete(child_recid); _children[hash] = 0; _recman.update(_recid, this); } } return existing; } } } /** * Calculates the hashcode of a key, based on the current directory * depth. */ private int hashCode(Object key) { int hashMask = hashMask(); int hash = key.hashCode(); hash = hash & hashMask; hash = hash >>> ((MAX_DEPTH - _depth) * BIT_SIZE); hash = hash % MAX_CHILDREN; /* System.out.println("HashDirectory.hashCode() is: 0x" +Integer.toHexString(hash) +" for object hashCode() 0x" +Integer.toHexString(key.hashCode())); */ return hash; } /** * Calculates the hashmask of this directory. The hashmask is the * bit mask applied to a hashcode to retain only bits that are * relevant to this directory level. */ int hashMask() { int bits = MAX_CHILDREN-1; int hashMask = bits << ((MAX_DEPTH - _depth) * BIT_SIZE); /* System.out.println("HashDirectory.hashMask() is: 0x" +Integer.toHexString(hashMask)); */ return hashMask; } /** * Returns an enumeration of the keys contained in this */ FastIterator keys() throws IOException { return new HDIterator( true ); } /** * Returns an enumeration of the values contained in this */ FastIterator values() throws IOException { return new HDIterator( false ); } /** * Implement Externalizable interface */ public void writeExternal(ObjectOutput out) throws IOException { out.writeByte(_depth); out.writeObject(_children); } /** * Implement Externalizable interface */ public synchronized void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { _depth = in.readByte(); _children = (long[])in.readObject(); } //////////////////////////////////////////////////////////////////////// // INNER CLASS //////////////////////////////////////////////////////////////////////// /** * Utility class to enumerate keys/values in a HTree */ public class HDIterator extends FastIterator { /** * True if we're iterating on keys, False if enumerating on values. */ private boolean _iterateKeys; /** * Stacks of directories & last enumerated child position */ private ArrayList _dirStack; private ArrayList _childStack; /** * Current HashDirectory in the hierarchy */ private HashDirectory _dir; /** * Current child position */ private int _child; /** * Current bucket iterator */ private Iterator _iter; /** * Construct an iterator on this directory. * * @param iterateKeys True if iteration supplies keys, False * if iterateKeys supplies values. */ HDIterator( boolean iterateKeys ) throws IOException { _dirStack = new ArrayList(); _childStack = new ArrayList(); _dir = HashDirectory.this; _child = -1; _iterateKeys = iterateKeys; prepareNext(); } /** * Returns the next object. */ public Object next() { Object next = null; if( _iter != null && _iter.hasNext() ) { next = _iter.next(); } else { try { prepareNext(); } catch ( IOException except ) { throw new IterationException( except ); } if ( _iter != null && _iter.hasNext() ) { return next(); } } return next; } /** * Prepare internal state so we can answer hasMoreElements * * Actually, this code prepares an Enumeration on the next * Bucket to enumerate. If no following bucket is found, * the next Enumeration is set to null. */ private void prepareNext() throws IOException { long child_recid = 0; // find next bucket/directory to enumerate do { _child++; if (_child >= MAX_CHILDREN) { if (_dirStack.isEmpty()) { // no more directory in the stack, we're finished return; } // try next page _dir = (HashDirectory) _dirStack.remove( _dirStack.size()-1 ); _child = ( (Integer) _childStack.remove( _childStack.size()-1 ) ).intValue(); continue; } child_recid = _dir._children[_child]; } while (child_recid == 0); if (child_recid == 0) { throw new Error("child_recid cannot be 0"); } HashNode node = (HashNode) _recman.fetch( child_recid ); // System.out.println("HDEnumeration.get() child is : "+node); if ( node instanceof HashDirectory ) { // save current position _dirStack.add( _dir ); _childStack.add( new Integer( _child ) ); _dir = (HashDirectory)node; _child = -1; // recurse into _dir.setPersistenceContext( _recman, child_recid ); prepareNext(); } else { // node is a bucket HashBucket bucket = (HashBucket)node; if ( _iterateKeys ) { _iter = bucket.getKeys().iterator(); } else { _iter = bucket.getValues().iterator(); } } } } } libjdbm-java-1.0.orig/src/main/jdbm/htree/HashNode.java0000644000175000017500000000476210276576000022677 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.htree; import java.io.Serializable; /** * Abstract class for Hashtable directory nodes * * @author Alex Boisvert * @version $Id: HashNode.java,v 1.2 2003/03/21 02:54:58 boisvert Exp $ */ class HashNode implements Serializable { // Empty, there's no common functionality. We use this abstract // class for typing only. } libjdbm-java-1.0.orig/src/main/jdbm/htree/HTree.java0000644000175000017500000001263310276576000022211 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are (C) Copyright 2000 by their associated contributors. * */ package jdbm.htree; import jdbm.RecordManager; import jdbm.helper.FastIterator; import java.io.IOException; /** * Persistent hashtable implementation for PageManager. * Implemented as an H*Tree structure. * * WARNING! If this instance is used in a transactional context, it * *must* be discarded after a rollback. * * @author Alex Boisvert * @version $Id: HTree.java,v 1.3 2005/06/25 23:12:32 doomdark Exp $ */ public class HTree { /** * Root hash directory. */ private HashDirectory _root; /** * Private constructor * * @param root Root hash directory. */ private HTree( HashDirectory root ) { _root = root; } /** * Create a persistent hashtable. * * @param recman Record manager used for persistence. */ public static HTree createInstance( RecordManager recman ) throws IOException { HashDirectory root; long recid; root = new HashDirectory( (byte) 0 ); recid = recman.insert( root ); root.setPersistenceContext( recman, recid ); return new HTree( root ); } /** * Load a persistent hashtable * * @param recman RecordManager used to store the persistent hashtable * @param root_recid Record id of the root directory of the HTree */ public static HTree load( RecordManager recman, long root_recid ) throws IOException { HTree tree; HashDirectory root; root = (HashDirectory) recman.fetch( root_recid ); root.setPersistenceContext( recman, root_recid ); tree = new HTree( root ); return tree; } /** * Associates the specified value with the specified key. * * @param key key with which the specified value is to be assocated. * @param value value to be associated with the specified key. */ public synchronized void put(Object key, Object value) throws IOException { _root.put(key, value); } /** * Returns the value which is associated with the given key. Returns * null if there is not association for this key. * * @param key key whose associated value is to be returned */ public synchronized Object get(Object key) throws IOException { return _root.get(key); } /** * Remove the value which is associated with the given key. If the * key does not exist, this method simply ignores the operation. * * @param key key whose associated value is to be removed */ public synchronized void remove(Object key) throws IOException { _root.remove(key); } /** * Returns an enumeration of the keys contained in this */ public synchronized FastIterator keys() throws IOException { return _root.keys(); } /** * Returns an enumeration of the values contained in this */ public synchronized FastIterator values() throws IOException { return _root.values(); } /** * Get the record identifier used to load this hashtable. */ public long getRecid() { return _root.getRecid(); } } libjdbm-java-1.0.orig/src/main/jdbm/htree/package.html0000644000175000017500000000061410276576000022614 0ustar twernertwerner

HTree (scalable persistent hashtable) data structure implementation.

Version:
$Revision: 1.1 $ $Date: 2002/05/31 06:33:20 $
Author:
Alex Boisvert
libjdbm-java-1.0.orig/src/main/jdbm/recman/0000775000175000017500000000000010276576000020472 5ustar twernertwernerlibjdbm-java-1.0.orig/src/main/jdbm/recman/BaseRecordManager.java0000644000175000017500000003477010276576000024652 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: BaseRecordManager.java,v 1.8 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.IOException; import java.util.HashMap; import java.util.Map; import jdbm.RecordManager; import jdbm.helper.Serializer; import jdbm.helper.DefaultSerializer; /** * This class manages records, which are uninterpreted blobs of data. The * set of operations is simple and straightforward: you communicate with * the class using long "rowids" and byte[] data blocks. Rowids are returned * on inserts and you can stash them away someplace safe to be able to get * back to them. Data blocks can be as long as you wish, and may have * lengths different from the original when updating. *

* Operations are synchronized, so that only one of them will happen * concurrently even if you hammer away from multiple threads. Operations * are made atomic by keeping a transaction log which is recovered after * a crash, so the operations specified by this interface all have ACID * properties. *

* You identify a file by just the name. The package attaches .db * for the database file, and .lg for the transaction log. The * transaction log is synchronized regularly and then restarted, so don't * worry if you see the size going up and down. * * @author Alex Boisvert * @author Cees de Groot * @version $Id: BaseRecordManager.java,v 1.8 2005/06/25 23:12:32 doomdark Exp $ */ public final class BaseRecordManager implements RecordManager { /** * Underlying record file. */ private RecordFile _file; /** * Physical row identifier manager. */ private PhysicalRowIdManager _physMgr; /** * Logigal to Physical row identifier manager. */ private LogicalRowIdManager _logMgr; /** * Page manager. */ private PageManager _pageman; /** * Reserved slot for name directory. */ public static final int NAME_DIRECTORY_ROOT = 0; /** * Static debugging flag */ public static final boolean DEBUG = false; /** * Directory of named JDBMHashtables. This directory is a persistent * directory, stored as a Hashtable. It can be retrived by using * the NAME_DIRECTORY_ROOT. */ private Map _nameDirectory; /** * Creates a record manager for the indicated file * * @throws IOException when the file cannot be opened or is not * a valid file content-wise. */ public BaseRecordManager( String filename ) throws IOException { _file = new RecordFile( filename ); _pageman = new PageManager( _file ); _physMgr = new PhysicalRowIdManager( _file, _pageman ); _logMgr = new LogicalRowIdManager( _file, _pageman ); } /** * Get the underlying Transaction Manager */ public synchronized TransactionManager getTransactionManager() { checkIfClosed(); return _file.txnMgr; } /** * Switches off transactioning for the record manager. This means * that a) a transaction log is not kept, and b) writes aren't * synch'ed after every update. This is useful when batch inserting * into a new database. *

* Only call this method directly after opening the file, otherwise * the results will be undefined. */ public synchronized void disableTransactions() { checkIfClosed(); _file.disableTransactions(); } /** * Closes the record manager. * * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void close() throws IOException { checkIfClosed(); _pageman.close(); _pageman = null; _file.close(); _file = null; } /** * Inserts a new record using standard java object serialization. * * @param obj the object for the new record. * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public long insert( Object obj ) throws IOException { return insert( obj, DefaultSerializer.INSTANCE ); } /** * Inserts a new record using a custom serializer. * * @param obj the object for the new record. * @param serializer a custom serializer * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized long insert( Object obj, Serializer serializer ) throws IOException { byte[] data; long recid; Location physRowId; checkIfClosed(); data = serializer.serialize( obj ); physRowId = _physMgr.insert( data, 0, data.length ); recid = _logMgr.insert( physRowId ).toLong(); if ( DEBUG ) { System.out.println( "BaseRecordManager.insert() recid " + recid + " length " + data.length ) ; } return recid; } /** * Deletes a record. * * @param recid the rowid for the record that should be deleted. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void delete( long recid ) throws IOException { checkIfClosed(); if ( recid <= 0 ) { throw new IllegalArgumentException( "Argument 'recid' is invalid: " + recid ); } if ( DEBUG ) { System.out.println( "BaseRecordManager.delete() recid " + recid ) ; } Location logRowId = new Location( recid ); Location physRowId = _logMgr.fetch( logRowId ); _physMgr.delete( physRowId ); _logMgr.delete( logRowId ); } /** * Updates a record using standard java object serialization. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @throws IOException when one of the underlying I/O operations fails. */ public void update( long recid, Object obj ) throws IOException { update( recid, obj, DefaultSerializer.INSTANCE ); } /** * Updates a record using a custom serializer. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @param serializer a custom serializer * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void update( long recid, Object obj, Serializer serializer ) throws IOException { checkIfClosed(); if ( recid <= 0 ) { throw new IllegalArgumentException( "Argument 'recid' is invalid: " + recid ); } Location logRecid = new Location( recid ); Location physRecid = _logMgr.fetch( logRecid ); byte[] data = serializer.serialize( obj ); if ( DEBUG ) { System.out.println( "BaseRecordManager.update() recid " + recid + " length " + data.length ) ; } Location newRecid = _physMgr.update( physRecid, data, 0, data.length ); if ( ! newRecid.equals( physRecid ) ) { _logMgr.update( logRecid, newRecid ); } } /** * Fetches a record using standard java object serialization. * * @param recid the recid for the record that must be fetched. * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public Object fetch( long recid ) throws IOException { return fetch( recid, DefaultSerializer.INSTANCE ); } /** * Fetches a record using a custom serializer. * * @param recid the recid for the record that must be fetched. * @param serializer a custom serializer * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized Object fetch( long recid, Serializer serializer ) throws IOException { byte[] data; checkIfClosed(); if ( recid <= 0 ) { throw new IllegalArgumentException( "Argument 'recid' is invalid: " + recid ); } data = _physMgr.fetch( _logMgr.fetch( new Location( recid ) ) ); if ( DEBUG ) { System.out.println( "BaseRecordManager.fetch() recid " + recid + " length " + data.length ) ; } return serializer.deserialize( data ); } /** * Returns the number of slots available for "root" rowids. These slots * can be used to store special rowids, like rowids that point to * other rowids. Root rowids are useful for bootstrapping access to * a set of data. */ public int getRootCount() { return FileHeader.NROOTS; } /** * Returns the indicated root rowid. * * @see #getRootCount */ public synchronized long getRoot( int id ) throws IOException { checkIfClosed(); return _pageman.getFileHeader().getRoot( id ); } /** * Sets the indicated root rowid. * * @see #getRootCount */ public synchronized void setRoot( int id, long rowid ) throws IOException { checkIfClosed(); _pageman.getFileHeader().setRoot( id, rowid ); } /** * Obtain the record id of a named object. Returns 0 if named object * doesn't exist. */ public long getNamedObject( String name ) throws IOException { checkIfClosed(); Map nameDirectory = getNameDirectory(); Long recid = (Long) nameDirectory.get( name ); if ( recid == null ) { return 0; } return recid.longValue(); } /** * Set the record id of a named object. */ public void setNamedObject( String name, long recid ) throws IOException { checkIfClosed(); Map nameDirectory = getNameDirectory(); if ( recid == 0 ) { // remove from hashtable nameDirectory.remove( name ); } else { nameDirectory.put( name, new Long( recid ) ); } saveNameDirectory( nameDirectory ); } /** * Commit (make persistent) all changes since beginning of transaction. */ public synchronized void commit() throws IOException { checkIfClosed(); _pageman.commit(); } /** * Rollback (cancel) all changes since beginning of transaction. */ public synchronized void rollback() throws IOException { checkIfClosed(); _pageman.rollback(); } /** * Load name directory */ private Map getNameDirectory() throws IOException { // retrieve directory of named hashtable long nameDirectory_recid = getRoot( NAME_DIRECTORY_ROOT ); if ( nameDirectory_recid == 0 ) { _nameDirectory = new HashMap(); nameDirectory_recid = insert( _nameDirectory ); setRoot( NAME_DIRECTORY_ROOT, nameDirectory_recid ); } else { _nameDirectory = (Map) fetch( nameDirectory_recid ); } return _nameDirectory; } private void saveNameDirectory( Map directory ) throws IOException { long recid = getRoot( NAME_DIRECTORY_ROOT ); if ( recid == 0 ) { throw new IOException( "Name directory must exist" ); } update( recid, _nameDirectory ); } /** * Check if RecordManager has been closed. If so, throw an * IllegalStateException. */ private void checkIfClosed() throws IllegalStateException { if ( _file == null ) { throw new IllegalStateException( "RecordManager has been closed" ); } } } libjdbm-java-1.0.orig/src/main/jdbm/recman/BlockIo.java0000644000175000017500000002175410276576000022666 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: BlockIo.java,v 1.2 2002/08/06 05:18:36 boisvert Exp $ */ package jdbm.recman; import java.io.*; /** * This class wraps a page-sized byte array and provides methods * to read and write data to and from it. The readers and writers * are just the ones that the rest of the toolkit needs, nothing else. * Values written are compatible with java.io routines. * * @see java.io.DataInput * @see java.io.DataOutput */ public final class BlockIo implements java.io.Externalizable { public final static long serialVersionUID = 2L; private long blockId; private transient byte[] data; // work area private transient BlockView view = null; private transient boolean dirty = false; private transient int transactionCount = 0; /** * Default constructor for serialization */ public BlockIo() { // empty } /** * Constructs a new BlockIo instance working on the indicated * buffer. */ BlockIo(long blockId, byte[] data) { // removeme for production version if (blockId > 10000000000L) throw new Error("bogus block id " + blockId); this.blockId = blockId; this.data = data; } /** * Returns the underlying array */ byte[] getData() { return data; } /** * Sets the block number. Should only be called by RecordFile. */ void setBlockId(long id) { if (isInTransaction()) throw new Error("BlockId assigned for transaction block"); // removeme for production version if (id > 10000000000L) throw new Error("bogus block id " + id); blockId = id; } /** * Returns the block number. */ long getBlockId() { return blockId; } /** * Returns the current view of the block. */ public BlockView getView() { return view; } /** * Sets the current view of the block. */ public void setView(BlockView view) { this.view = view; } /** * Sets the dirty flag */ void setDirty() { dirty = true; } /** * Clears the dirty flag */ void setClean() { dirty = false; } /** * Returns true if the dirty flag is set. */ boolean isDirty() { return dirty; } /** * Returns true if the block is still dirty with respect to the * transaction log. */ boolean isInTransaction() { return transactionCount != 0; } /** * Increments transaction count for this block, to signal that this * block is in the log but not yet in the data file. The method also * takes a snapshot so that the data may be modified in new transactions. */ synchronized void incrementTransactionCount() { transactionCount++; // @fixme(alex) setClean(); } /** * Decrements transaction count for this block, to signal that this * block has been written from the log to the data file. */ synchronized void decrementTransactionCount() { transactionCount--; if (transactionCount < 0) throw new Error("transaction count on block " + getBlockId() + " below zero!"); } /** * Reads a byte from the indicated position */ public byte readByte(int pos) { return data[pos]; } /** * Writes a byte to the indicated position */ public void writeByte(int pos, byte value) { data[pos] = value; setDirty(); } /** * Reads a short from the indicated position */ public short readShort(int pos) { return (short) (((short) (data[pos+0] & 0xff) << 8) | ((short) (data[pos+1] & 0xff) << 0)); } /** * Writes a short to the indicated position */ public void writeShort(int pos, short value) { data[pos+0] = (byte)(0xff & (value >> 8)); data[pos+1] = (byte)(0xff & (value >> 0)); setDirty(); } /** * Reads an int from the indicated position */ public int readInt(int pos) { return (((int)(data[pos+0] & 0xff) << 24) | ((int)(data[pos+1] & 0xff) << 16) | ((int)(data[pos+2] & 0xff) << 8) | ((int)(data[pos+3] & 0xff) << 0)); } /** * Writes an int to the indicated position */ public void writeInt(int pos, int value) { data[pos+0] = (byte)(0xff & (value >> 24)); data[pos+1] = (byte)(0xff & (value >> 16)); data[pos+2] = (byte)(0xff & (value >> 8)); data[pos+3] = (byte)(0xff & (value >> 0)); setDirty(); } /** * Reads a long from the indicated position */ public long readLong( int pos ) { // Contributed by Erwin Bolwidt // Gives about 15% performance improvement return ( (long)( ((data[pos+0] & 0xff) << 24) | ((data[pos+1] & 0xff) << 16) | ((data[pos+2] & 0xff) << 8) | ((data[pos+3] & 0xff) ) ) << 32 ) | ( (long)( ((data[pos+4] & 0xff) << 24) | ((data[pos+5] & 0xff) << 16) | ((data[pos+6] & 0xff) << 8) | ((data[pos+7] & 0xff) ) ) & 0xffffffff ); /* Original version by Alex Boisvert. Might be faster on 64-bit JVMs. return (((long)(data[pos+0] & 0xff) << 56) | ((long)(data[pos+1] & 0xff) << 48) | ((long)(data[pos+2] & 0xff) << 40) | ((long)(data[pos+3] & 0xff) << 32) | ((long)(data[pos+4] & 0xff) << 24) | ((long)(data[pos+5] & 0xff) << 16) | ((long)(data[pos+6] & 0xff) << 8) | ((long)(data[pos+7] & 0xff) << 0)); */ } /** * Writes a long to the indicated position */ public void writeLong(int pos, long value) { data[pos+0] = (byte)(0xff & (value >> 56)); data[pos+1] = (byte)(0xff & (value >> 48)); data[pos+2] = (byte)(0xff & (value >> 40)); data[pos+3] = (byte)(0xff & (value >> 32)); data[pos+4] = (byte)(0xff & (value >> 24)); data[pos+5] = (byte)(0xff & (value >> 16)); data[pos+6] = (byte)(0xff & (value >> 8)); data[pos+7] = (byte)(0xff & (value >> 0)); setDirty(); } // overrides java.lang.Object public String toString() { return "BlockIO(" + blockId + "," + dirty + "," + view + ")"; } // implement externalizable interface public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { blockId = in.readLong(); int length = in.readInt(); data = new byte[length]; in.readFully(data); } // implement externalizable interface public void writeExternal(ObjectOutput out) throws IOException { out.writeLong(blockId); out.writeInt(data.length); out.write(data); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/BlockView.java0000644000175000017500000000440410276576000023222 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: BlockView.java,v 1.2 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; /** * This is a marker interface that is implemented by classes that * interpret blocks of data by pretending to be an overlay. * * @see BlockIo#setView */ public interface BlockView { } libjdbm-java-1.0.orig/src/main/jdbm/recman/CacheRecordManager.java0000644000175000017500000003113610276576000024774 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: CacheRecordManager.java,v 1.9 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import jdbm.RecordManager; import jdbm.helper.CacheEvictionException; import jdbm.helper.CachePolicy; import jdbm.helper.CachePolicyListener; import jdbm.helper.DefaultSerializer; import jdbm.helper.Serializer; import jdbm.helper.WrappedRuntimeException; import java.io.IOException; import java.util.Enumeration; /** * A RecordManager wrapping and caching another RecordManager. * * @author Alex Boisvert * @author Cees de Groot * @version $Id: CacheRecordManager.java,v 1.9 2005/06/25 23:12:32 doomdark Exp $ */ public class CacheRecordManager implements RecordManager { /** * Wrapped RecordManager */ protected RecordManager _recman; /** * Cache for underlying RecordManager */ protected CachePolicy _cache; /** * Construct a CacheRecordManager wrapping another RecordManager and * using a given cache policy. * * @param recman Wrapped RecordManager * @param cache Cache policy */ public CacheRecordManager( RecordManager recman, CachePolicy cache ) { if ( recman == null ) { throw new IllegalArgumentException( "Argument 'recman' is null" ); } if ( cache == null ) { throw new IllegalArgumentException( "Argument 'cache' is null" ); } _recman = recman; _cache = cache; _cache.addListener( new CacheListener() ); } /** * Get the underlying Record Manager. * * @return underlying RecordManager or null if CacheRecordManager has * been closed. */ public RecordManager getRecordManager() { return _recman; } /** * Get the underlying cache policy * * @return underlying CachePolicy or null if CacheRecordManager has * been closed. */ public CachePolicy getCachePolicy() { return _cache; } /** * Inserts a new record using a custom serializer. * * @param obj the object for the new record. * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public long insert( Object obj ) throws IOException { return insert( obj, DefaultSerializer.INSTANCE ); } /** * Inserts a new record using a custom serializer. * * @param obj the object for the new record. * @param serializer a custom serializer * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized long insert( Object obj, Serializer serializer ) throws IOException { checkIfClosed(); long recid = _recman.insert( obj, serializer ); try { _cache.put( new Long( recid ), new CacheEntry( recid, obj, serializer, false ) ); } catch ( CacheEvictionException except ) { throw new WrappedRuntimeException( except ); } return recid; } /** * Deletes a record. * * @param recid the rowid for the record that should be deleted. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void delete( long recid ) throws IOException { checkIfClosed(); _recman.delete( recid ); _cache.remove( new Long( recid ) ); } /** * Updates a record using standard Java serialization. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @throws IOException when one of the underlying I/O operations fails. */ public void update( long recid, Object obj ) throws IOException { update( recid, obj, DefaultSerializer.INSTANCE ); } /** * Updates a record using a custom serializer. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @param serializer a custom serializer * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void update( long recid, Object obj, Serializer serializer ) throws IOException { CacheEntry entry; Long id; checkIfClosed(); id = new Long( recid ); try { entry = (CacheEntry) _cache.get( id ); if ( entry != null ) { // reuse existing cache entry entry._obj = obj; entry._serializer = serializer; entry._isDirty = true; } else { _cache.put( id, new CacheEntry( recid, obj, serializer, true ) ); } } catch ( CacheEvictionException except ) { throw new IOException( except.getMessage() ); } } /** * Fetches a record using standard Java serialization. * * @param recid the recid for the record that must be fetched. * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public Object fetch( long recid ) throws IOException { return fetch( recid, DefaultSerializer.INSTANCE ); } /** * Fetches a record using a custom serializer. * * @param recid the recid for the record that must be fetched. * @param serializer a custom serializer * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public synchronized Object fetch( long recid, Serializer serializer ) throws IOException { checkIfClosed(); Long id = new Long( recid ); CacheEntry entry = (CacheEntry) _cache.get( id ); if ( entry == null ) { entry = new CacheEntry( recid, null, serializer, false ); entry._obj = _recman.fetch( recid, serializer ); try { _cache.put( id, entry ); } catch ( CacheEvictionException except ) { throw new WrappedRuntimeException( except ); } } return entry._obj; } /** * Closes the record manager. * * @throws IOException when one of the underlying I/O operations fails. */ public synchronized void close() throws IOException { checkIfClosed(); updateCacheEntries(); _recman.close(); _recman = null; _cache = null; } /** * Returns the number of slots available for "root" rowids. These slots * can be used to store special rowids, like rowids that point to * other rowids. Root rowids are useful for bootstrapping access to * a set of data. */ public synchronized int getRootCount() { checkIfClosed(); return _recman.getRootCount(); } /** * Returns the indicated root rowid. * * @see #getRootCount */ public synchronized long getRoot( int id ) throws IOException { checkIfClosed(); return _recman.getRoot( id ); } /** * Sets the indicated root rowid. * * @see #getRootCount */ public synchronized void setRoot( int id, long rowid ) throws IOException { checkIfClosed(); _recman.setRoot( id, rowid ); } /** * Commit (make persistent) all changes since beginning of transaction. */ public synchronized void commit() throws IOException { checkIfClosed(); updateCacheEntries(); _recman.commit(); } /** * Rollback (cancel) all changes since beginning of transaction. */ public synchronized void rollback() throws IOException { checkIfClosed(); _recman.rollback(); // discard all cache entries since we don't know which entries // where part of the transaction _cache.removeAll(); } /** * Obtain the record id of a named object. Returns 0 if named object * doesn't exist. */ public synchronized long getNamedObject( String name ) throws IOException { checkIfClosed(); return _recman.getNamedObject( name ); } /** * Set the record id of a named object. */ public synchronized void setNamedObject( String name, long recid ) throws IOException { checkIfClosed(); _recman.setNamedObject( name, recid ); } /** * Check if RecordManager has been closed. If so, throw an * IllegalStateException */ private void checkIfClosed() throws IllegalStateException { if ( _recman == null ) { throw new IllegalStateException( "RecordManager has been closed" ); } } /** * Update all dirty cache objects to the underlying RecordManager. */ protected void updateCacheEntries() throws IOException { Enumeration enume = _cache.elements(); while ( enume.hasMoreElements() ) { CacheEntry entry = (CacheEntry) enume.nextElement(); if ( entry._isDirty ) { _recman.update( entry._recid, entry._obj, entry._serializer ); entry._isDirty = false; } } } private class CacheEntry { long _recid; Object _obj; Serializer _serializer; boolean _isDirty; CacheEntry( long recid, Object obj, Serializer serializer, boolean isDirty ) { _recid = recid; _obj = obj; _serializer = serializer; _isDirty = isDirty; } } // class CacheEntry private class CacheListener implements CachePolicyListener { /** Notification that cache is evicting an object * * @arg obj object evited from cache * */ public void cacheObjectEvicted( Object obj ) throws CacheEvictionException { CacheEntry entry = (CacheEntry) obj; if ( entry._isDirty ) { try { _recman.update( entry._recid, entry._obj, entry._serializer ); } catch ( IOException except ) { throw new CacheEvictionException( except ); } } } } } libjdbm-java-1.0.orig/src/main/jdbm/recman/DataPage.java0000644000175000017500000000631010276576000023001 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: DataPage.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * Class describing a page that holds data. */ final class DataPage extends PageHeader { // offsets private static final short O_FIRST = PageHeader.SIZE; // short firstrowid static final short O_DATA = (short)(O_FIRST + Magic.SZ_SHORT); static final short DATA_PER_PAGE = (short)(RecordFile.BLOCK_SIZE - O_DATA); /** * Constructs a data page view from the indicated block. */ DataPage(BlockIo block) { super(block); } /** * Factory method to create or return a data page for the * indicated block. */ static DataPage getDataPageView(BlockIo block) { BlockView view = block.getView(); if (view != null && view instanceof DataPage) return (DataPage) view; else return new DataPage(block); } /** Returns the first rowid's offset */ short getFirst() { return block.readShort(O_FIRST); } /** Sets the first rowid's offset */ void setFirst(short value) { paranoiaMagicOk(); if (value > 0 && value < O_DATA) throw new Error("DataPage.setFirst: offset " + value + " too small"); block.writeShort(O_FIRST, value); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/FileHeader.java0000644000175000017500000001236110276576000023326 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FileHeader.java,v 1.3 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; /** * This class represents a file header. It is a 1:1 representation of * the data that appears in block 0 of a file. */ class FileHeader implements BlockView { // offsets private static final short O_MAGIC = 0; // short magic private static final short O_LISTS = Magic.SZ_SHORT; // long[2*NLISTS] private static final int O_ROOTS = O_LISTS + (Magic.NLISTS * 2 * Magic.SZ_LONG); // my block private BlockIo block; /** The number of "root" rowids available in the file. */ static final int NROOTS = (RecordFile.BLOCK_SIZE - O_ROOTS) / Magic.SZ_LONG; /** * Constructs a FileHeader object from a block. * * @param block The block that contains the file header * @param isNew If true, the file header is for a new file. * @throws IOException if the block is too short to keep the file * header. */ FileHeader(BlockIo block, boolean isNew) { this.block = block; if (isNew) block.writeShort(O_MAGIC, Magic.FILE_HEADER); else if (!magicOk()) throw new Error("CRITICAL: file header magic not OK " + block.readShort(O_MAGIC)); } /** Returns true if the magic corresponds with the fileHeader magic. */ private boolean magicOk() { return block.readShort(O_MAGIC) == Magic.FILE_HEADER; } /** Returns the offset of the "first" block of the indicated list */ private short offsetOfFirst(int list) { return (short) (O_LISTS + (2 * Magic.SZ_LONG * list)); } /** Returns the offset of the "last" block of the indicated list */ private short offsetOfLast(int list) { return (short) (offsetOfFirst(list) + Magic.SZ_LONG); } /** Returns the offset of the indicated root */ private short offsetOfRoot(int root) { return (short) (O_ROOTS + (root * Magic.SZ_LONG)); } /** * Returns the first block of the indicated list */ long getFirstOf(int list) { return block.readLong(offsetOfFirst(list)); } /** * Sets the first block of the indicated list */ void setFirstOf(int list, long value) { block.writeLong(offsetOfFirst(list), value); } /** * Returns the last block of the indicated list */ long getLastOf(int list) { return block.readLong(offsetOfLast(list)); } /** * Sets the last block of the indicated list */ void setLastOf(int list, long value) { block.writeLong(offsetOfLast(list), value); } /** * Returns the indicated root rowid. A root rowid is a special rowid * that needs to be kept between sessions. It could conceivably be * stored in a special file, but as a large amount of space in the * block header is wasted anyway, it's more useful to store it where * it belongs. * * @see #NROOTS */ long getRoot(int root) { return block.readLong(offsetOfRoot(root)); } /** * Sets the indicated root rowid. * * @see #getRoot * @see #NROOTS */ void setRoot(int root, long rowid) { block.writeLong(offsetOfRoot(root), rowid); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/FreeLogicalRowIdPage.java0000644000175000017500000001173510276576000025260 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FreeLogicalRowIdPage.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * Class describing a page that holds logical rowids that were freed. Note * that the methods have *physical* rowids in their signatures - this is * because logical and physical rowids are internally the same, only their * external representation (i.e. in the client API) differs. */ class FreeLogicalRowIdPage extends PageHeader { // offsets private static final short O_COUNT = PageHeader.SIZE; // short count static final short O_FREE = (short)(O_COUNT + Magic.SZ_SHORT); static final short ELEMS_PER_PAGE = (short) ((RecordFile.BLOCK_SIZE - O_FREE) / PhysicalRowId.SIZE); // slots we returned. final PhysicalRowId[] slots = new PhysicalRowId[ELEMS_PER_PAGE]; /** * Constructs a data page view from the indicated block. */ FreeLogicalRowIdPage(BlockIo block) { super(block); } /** * Factory method to create or return a data page for the * indicated block. */ static FreeLogicalRowIdPage getFreeLogicalRowIdPageView(BlockIo block) { BlockView view = block.getView(); if (view != null && view instanceof FreeLogicalRowIdPage) return (FreeLogicalRowIdPage) view; else return new FreeLogicalRowIdPage(block); } /** Returns the number of free rowids */ short getCount() { return block.readShort(O_COUNT); } /** Sets the number of free rowids */ private void setCount(short i) { block.writeShort(O_COUNT, i); } /** Frees a slot */ void free(int slot) { get(slot).setBlock(0); setCount((short) (getCount() - 1)); } /** Allocates a slot */ PhysicalRowId alloc(int slot) { setCount((short) (getCount() + 1)); get(slot).setBlock(-1); return get(slot); } /** Returns true if a slot is allocated */ boolean isAllocated(int slot) { return get(slot).getBlock() > 0; } /** Returns true if a slot is free */ boolean isFree(int slot) { return !isAllocated(slot); } /** Returns the value of the indicated slot */ PhysicalRowId get(int slot) { if (slots[slot] == null) slots[slot] = new PhysicalRowId(block, slotToOffset(slot));; return slots[slot]; } /** Converts slot to offset */ private short slotToOffset(int slot) { return (short) (O_FREE + (slot * PhysicalRowId.SIZE)); } /** * Returns first free slot, -1 if no slots are available */ int getFirstFree() { for (int i = 0; i < ELEMS_PER_PAGE; i++) { if (isFree(i)) return i; } return -1; } /** * Returns first allocated slot, -1 if no slots are available. */ int getFirstAllocated() { for (int i = 0; i < ELEMS_PER_PAGE; i++) { if (isAllocated(i)) return i; } return -1; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/FreeLogicalRowIdPageManager.java0000644000175000017500000001214510276576000026547 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FreeLogicalRowIdPageManager.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; import java.io.IOException; /** * This class manages free Logical rowid pages and provides methods * to free and allocate Logical rowids on a high level. */ final class FreeLogicalRowIdPageManager { // our record file private RecordFile file; // our page manager private PageManager pageman; /** * Creates a new instance using the indicated record file and * page manager. */ FreeLogicalRowIdPageManager(RecordFile file, PageManager pageman) throws IOException { this.file = file; this.pageman = pageman; } /** * Returns a free Logical rowid, or * null if nothing was found. */ Location get() throws IOException { // Loop through the free Logical rowid list until we find // the first rowid. Location retval = null; PageCursor curs = new PageCursor(pageman, Magic.FREELOGIDS_PAGE); while (curs.next() != 0) { FreeLogicalRowIdPage fp = FreeLogicalRowIdPage .getFreeLogicalRowIdPageView(file.get(curs.getCurrent())); int slot = fp.getFirstAllocated(); if (slot != -1) { // got one! retval = new Location(fp.get(slot)); fp.free(slot); if (fp.getCount() == 0) { // page became empty - free it file.release(curs.getCurrent(), false); pageman.free(Magic.FREELOGIDS_PAGE, curs.getCurrent()); } else file.release(curs.getCurrent(), true); return retval; } else { // no luck, go to next page file.release(curs.getCurrent(), false); } } return null; } /** * Puts the indicated rowid on the free list */ void put(Location rowid) throws IOException { PhysicalRowId free = null; PageCursor curs = new PageCursor(pageman, Magic.FREELOGIDS_PAGE); long freePage = 0; while (curs.next() != 0) { freePage = curs.getCurrent(); BlockIo curBlock = file.get(freePage); FreeLogicalRowIdPage fp = FreeLogicalRowIdPage .getFreeLogicalRowIdPageView(curBlock); int slot = fp.getFirstFree(); if (slot != -1) { free = fp.alloc(slot); break; } file.release(curBlock); } if (free == null) { // No more space on the free list, add a page. freePage = pageman.allocate(Magic.FREELOGIDS_PAGE); BlockIo curBlock = file.get(freePage); FreeLogicalRowIdPage fp = FreeLogicalRowIdPage.getFreeLogicalRowIdPageView(curBlock); free = fp.alloc(0); } free.setBlock(rowid.getBlock()); free.setOffset(rowid.getOffset()); file.release(freePage, true); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/FreePhysicalRowId.java0000644000175000017500000000543410276576000024664 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FreePhysicalRowId.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * This class extends the physical rowid with a size value to indicated * the size of a free rowid on the free rowid list. */ final class FreePhysicalRowId extends PhysicalRowId { // offsets private static final short O_SIZE = PhysicalRowId.SIZE; // int size static final short SIZE = O_SIZE + Magic.SZ_INT; /** * Constructs a physical rowid from the indicated data starting at * the indicated position. */ FreePhysicalRowId(BlockIo block, short pos) { super(block, pos); } /** Returns the size */ int getSize() { return block.readInt(pos + O_SIZE); } /** Sets the size */ void setSize(int value) { block.writeInt(pos + O_SIZE, value); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/FreePhysicalRowIdPage.java0000644000175000017500000001120310276576000025450 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FreePhysicalRowIdPage.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * Class describing a page that holds physical rowids that were freed. */ final class FreePhysicalRowIdPage extends PageHeader { // offsets private static final short O_COUNT = PageHeader.SIZE; // short count static final short O_FREE = O_COUNT + Magic.SZ_SHORT; static final short ELEMS_PER_PAGE = (RecordFile.BLOCK_SIZE - O_FREE) / FreePhysicalRowId.SIZE; // slots we returned. FreePhysicalRowId[] slots = new FreePhysicalRowId[ELEMS_PER_PAGE]; /** * Constructs a data page view from the indicated block. */ FreePhysicalRowIdPage(BlockIo block) { super(block); } /** * Factory method to create or return a data page for the * indicated block. */ static FreePhysicalRowIdPage getFreePhysicalRowIdPageView(BlockIo block) { BlockView view = block.getView(); if (view != null && view instanceof FreePhysicalRowIdPage) return (FreePhysicalRowIdPage) view; else return new FreePhysicalRowIdPage(block); } /** Returns the number of free rowids */ short getCount() { return block.readShort(O_COUNT); } /** Sets the number of free rowids */ private void setCount(short i) { block.writeShort(O_COUNT, i); } /** Frees a slot */ void free(int slot) { get(slot).setSize(0); setCount((short) (getCount() - 1)); } /** Allocates a slot */ FreePhysicalRowId alloc(int slot) { setCount((short) (getCount() + 1)); return get(slot); } /** Returns true if a slot is allocated */ boolean isAllocated(int slot) { return get(slot).getSize() != 0; } /** Returns true if a slot is free */ boolean isFree(int slot) { return !isAllocated(slot); } /** Returns the value of the indicated slot */ FreePhysicalRowId get(int slot) { if (slots[slot] == null) slots[slot] = new FreePhysicalRowId(block, slotToOffset(slot));; return slots[slot]; } /** Converts slot to offset */ short slotToOffset(int slot) { return (short) (O_FREE + (slot * FreePhysicalRowId.SIZE)); } /** * Returns first free slot, -1 if no slots are available */ int getFirstFree() { for (int i = 0; i < ELEMS_PER_PAGE; i++) { if (isFree(i)) return i; } return -1; } /** * Returns first slot with available size >= indicated size, * or -1 if no slots are available. **/ int getFirstLargerThan(int size) { for (int i = 0; i < ELEMS_PER_PAGE; i++) { if (isAllocated(i) && get(i).getSize() >= size) return i; } return -1; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/FreePhysicalRowIdPageManager.java0000644000175000017500000001205310276576000026747 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: FreePhysicalRowIdPageManager.java,v 1.2 2001/11/17 16:14:25 boisvert Exp $ */ package jdbm.recman; import java.io.IOException; /** * This class manages free physical rowid pages and provides methods * to free and allocate physical rowids on a high level. */ final class FreePhysicalRowIdPageManager { // our record file protected RecordFile _file; // our page manager protected PageManager _pageman; /** * Creates a new instance using the indicated record file and * page manager. */ FreePhysicalRowIdPageManager( RecordFile file, PageManager pageman ) throws IOException { _file = file; _pageman = pageman; } /** * Returns a free physical rowid of the indicated size, or * null if nothing was found. */ Location get( int size ) throws IOException { // Loop through the free physical rowid list until we find // a rowid that's large enough. Location retval = null; PageCursor curs = new PageCursor( _pageman, Magic.FREEPHYSIDS_PAGE ); while (curs.next() != 0) { FreePhysicalRowIdPage fp = FreePhysicalRowIdPage .getFreePhysicalRowIdPageView( _file.get( curs.getCurrent() ) ); int slot = fp.getFirstLargerThan( size ); if ( slot != -1 ) { // got one! retval = new Location( fp.get( slot ) ); int slotsize = fp.get( slot ).getSize(); fp.free( slot ); if ( fp.getCount() == 0 ) { // page became empty - free it _file.release( curs.getCurrent(), false ); _pageman.free( Magic.FREEPHYSIDS_PAGE, curs.getCurrent() ); } else { _file.release( curs.getCurrent(), true ); } return retval; } else { // no luck, go to next page _file.release( curs.getCurrent(), false ); } } return null; } /** * Puts the indicated rowid on the free list */ void put(Location rowid, int size) throws IOException { FreePhysicalRowId free = null; PageCursor curs = new PageCursor(_pageman, Magic.FREEPHYSIDS_PAGE); long freePage = 0; while (curs.next() != 0) { freePage = curs.getCurrent(); BlockIo curBlock = _file.get(freePage); FreePhysicalRowIdPage fp = FreePhysicalRowIdPage .getFreePhysicalRowIdPageView(curBlock); int slot = fp.getFirstFree(); if (slot != -1) { free = fp.alloc(slot); break; } _file.release(curBlock); } if (free == null) { // No more space on the free list, add a page. freePage = _pageman.allocate(Magic.FREEPHYSIDS_PAGE); BlockIo curBlock = _file.get(freePage); FreePhysicalRowIdPage fp = FreePhysicalRowIdPage.getFreePhysicalRowIdPageView(curBlock); free = fp.alloc(0); } free.setBlock(rowid.getBlock()); free.setOffset(rowid.getOffset()); free.setSize(size); _file.release(freePage, true); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/Location.java0000644000175000017500000000750310276576000023110 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: Location.java,v 1.2 2003/11/01 14:17:21 dranatunga Exp $ */ package jdbm.recman; /** * This class represents a location within a file. Both physical and * logical rowids are based on locations internally - this version is * used when there is no file block to back the location's data. */ final class Location { private long block; private short offset; /** * Creates a location from a (block, offset) tuple. */ Location(long block, short offset) { this.block = block; this.offset = offset; } /** * Creates a location from a combined block/offset long, as * used in the external representation of logical rowids. * * @see #toLong() */ Location(long blockOffset) { this.offset = (short) (blockOffset & 0xffff); this.block = blockOffset >> 16; } /** * Creates a location based on the data of the physical rowid. */ Location(PhysicalRowId src) { block = src.getBlock(); offset = src.getOffset(); } /** * Returns the file block of the location */ long getBlock() { return block; } /** * Returns the offset within the block of the location */ short getOffset() { return offset; } /** * Returns the external representation of a location when used * as a logical rowid, which combines the block and the offset * in a single long. */ long toLong() { return (block << 16) + (long) offset; } // overrides of java.lang.Object public boolean equals(Object o) { if (o == null || !(o instanceof Location)) return false; Location ol = (Location) o; return ol.block == block && ol.offset == offset; } public String toString() { return "PL(" + block + ":" + offset + ")"; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/LogicalRowIdManager.java0000644000175000017500000001134010276576000025144 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: LogicalRowIdManager.java,v 1.3 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.IOException; /** * This class manages the linked lists of logical rowid pages. */ final class LogicalRowIdManager { // our record file and associated page manager private RecordFile file; private PageManager pageman; private FreeLogicalRowIdPageManager freeman; /** * Creates a log rowid manager using the indicated record file and * page manager */ LogicalRowIdManager(RecordFile file, PageManager pageman) throws IOException { this.file = file; this.pageman = pageman; this.freeman = new FreeLogicalRowIdPageManager(file, pageman); } /** * Creates a new logical rowid pointing to the indicated physical * id */ Location insert(Location loc) throws IOException { // check whether there's a free rowid to reuse Location retval = freeman.get(); if (retval == null) { // no. This means that we bootstrap things by allocating // a new translation page and freeing all the rowids on it. long firstPage = pageman.allocate(Magic.TRANSLATION_PAGE); short curOffset = TranslationPage.O_TRANS; for (int i = 0; i < TranslationPage.ELEMS_PER_PAGE; i++) { freeman.put(new Location(firstPage, curOffset)); curOffset += PhysicalRowId.SIZE; } retval = freeman.get(); if (retval == null) { throw new Error("couldn't obtain free translation"); } } // write the translation. update(retval, loc); return retval; } /** * Releases the indicated logical rowid. */ void delete(Location rowid) throws IOException { freeman.put(rowid); } /** * Updates the mapping * * @param rowid The logical rowid * @param loc The physical rowid */ void update(Location rowid, Location loc) throws IOException { TranslationPage xlatPage = TranslationPage.getTranslationPageView( file.get(rowid.getBlock())); PhysicalRowId physid = xlatPage.get(rowid.getOffset()); physid.setBlock(loc.getBlock()); physid.setOffset(loc.getOffset()); file.release(rowid.getBlock(), true); } /** * Returns a mapping * * @param rowid The logical rowid * @return The physical rowid */ Location fetch(Location rowid) throws IOException { TranslationPage xlatPage = TranslationPage.getTranslationPageView( file.get(rowid.getBlock())); try { Location retval = new Location(xlatPage.get(rowid.getOffset())); return retval; } finally { file.release(rowid.getBlock(), false); } } } libjdbm-java-1.0.orig/src/main/jdbm/recman/Magic.java0000644000175000017500000000615410276576000022361 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: Magic.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * This interface contains magic cookies. */ public interface Magic { /** Magic cookie at start of file */ public short FILE_HEADER = 0x1350; /** Magic for blocks. They're offset by the block type magic codes. */ public short BLOCK = 0x1351; /** Magics for blocks in certain lists. Offset by baseBlockMagic */ short FREE_PAGE = 0; short USED_PAGE = 1; short TRANSLATION_PAGE = 2; short FREELOGIDS_PAGE = 3; short FREEPHYSIDS_PAGE = 4; /** Number of lists in a file */ public short NLISTS = 5; /** * Maximum number of blocks in a file, leaving room for a 16 bit * offset encoded within a long. */ long MAX_BLOCKS = 0x7FFFFFFFFFFFL; /** Magic for transaction file */ short LOGFILE_HEADER = 0x1360; /** Size of an externalized byte */ public short SZ_BYTE = 1; /** Size of an externalized short */ public short SZ_SHORT = 2; /** Size of an externalized int */ public short SZ_INT = 4; /** Size of an externalized long */ public short SZ_LONG = 8; } libjdbm-java-1.0.orig/src/main/jdbm/recman/package.html0000644000175000017500000000060510276576000022752 0ustar twernertwerner

Core classes for managing persistent objects and processing transactions.

Version:
$Revision: 1.1 $ $Date: 2001/05/19 16:01:33 $
Author:
Alex Boisvert
libjdbm-java-1.0.orig/src/main/jdbm/recman/PageCursor.java0000644000175000017500000000645710276576000023421 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: PageCursor.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; import java.io.IOException; /** * This class provides a cursor that can follow lists of pages * bi-directionally. */ final class PageCursor { PageManager pageman; long current; short type; /** * Constructs a page cursor that starts at the indicated block. */ PageCursor(PageManager pageman, long current) { this.pageman = pageman; this.current = current; } /** * Constructs a page cursor that starts at the first block * of the indicated list. */ PageCursor(PageManager pageman, short type) throws IOException { this.pageman = pageman; this.type = type; } /** * Returns the current value of the cursor. */ long getCurrent() throws IOException { return current; } /** * Returns the next value of the cursor */ long next() throws IOException { if (current == 0) current = pageman.getFirst(type); else current = pageman.getNext(current); return current; } /** * Returns the previous value of the cursor */ long prev() throws IOException { current = pageman.getPrev(current); return current; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/PageHeader.java0000644000175000017500000001174510276576000023330 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: PageHeader.java,v 1.2 2003/09/21 15:47:01 boisvert Exp $ */ package jdbm.recman; /** * This class represents a page header. It is the common superclass for * all different page views. */ public class PageHeader implements BlockView { // offsets private static final short O_MAGIC = 0; // short magic private static final short O_NEXT = Magic.SZ_SHORT; // long next private static final short O_PREV = O_NEXT + Magic.SZ_LONG; // long prev protected static final short SIZE = O_PREV + Magic.SZ_LONG; // my block protected BlockIo block; /** * Constructs a PageHeader object from a block * * @param block The block that contains the file header * @throws IOException if the block is too short to keep the file * header. */ protected PageHeader(BlockIo block) { initialize(block); if (!magicOk()) throw new Error("CRITICAL: page header magic for block " + block.getBlockId() + " not OK " + getMagic()); } /** * Constructs a new PageHeader of the indicated type. Used for newly * created pages. */ PageHeader(BlockIo block, short type) { initialize(block); setType(type); } /** * Factory method to create or return a page header for the * indicated block. */ static PageHeader getView(BlockIo block) { BlockView view = block.getView(); if (view != null && view instanceof PageHeader) return (PageHeader) view; else return new PageHeader(block); } private void initialize(BlockIo block) { this.block = block; block.setView(this); } /** * Returns true if the magic corresponds with the fileHeader magic. */ private boolean magicOk() { int magic = getMagic(); return magic >= Magic.BLOCK && magic <= (Magic.BLOCK + Magic.FREEPHYSIDS_PAGE); } /** * For paranoia mode */ protected void paranoiaMagicOk() { if (!magicOk()) throw new Error("CRITICAL: page header magic not OK " + getMagic()); } /** Returns the magic code */ short getMagic() { return block.readShort(O_MAGIC); } /** Returns the next block. */ long getNext() { paranoiaMagicOk(); return block.readLong(O_NEXT); } /** Sets the next block. */ void setNext(long next) { paranoiaMagicOk(); block.writeLong(O_NEXT, next); } /** Returns the previous block. */ long getPrev() { paranoiaMagicOk(); return block.readLong(O_PREV); } /** Sets the previous block. */ void setPrev(long prev) { paranoiaMagicOk(); block.writeLong(O_PREV, prev); } /** Sets the type of the page header */ void setType(short type) { block.writeShort(O_MAGIC, (short) (Magic.BLOCK + type)); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/PageManager.java0000644000175000017500000002072410276576000023507 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: PageManager.java,v 1.3 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.*; /** * This class manages the linked lists of pages that make up a file. */ final class PageManager { // our record file private RecordFile file; // header data private FileHeader header; private BlockIo headerBuf; /** * Creates a new page manager using the indicated record file. */ PageManager(RecordFile file) throws IOException { this.file = file; // check the file header. If the magic is 0, we assume a new // file. Note that we hold on to the file header node. headerBuf = file.get(0); if (headerBuf.readShort(0) == 0) header = new FileHeader(headerBuf, true); else header = new FileHeader(headerBuf, false); } /** * Allocates a page of the indicated type. Returns recid of the * page. */ long allocate(short type) throws IOException { if (type == Magic.FREE_PAGE) throw new Error("allocate of free page?"); // do we have something on the free list? long retval = header.getFirstOf(Magic.FREE_PAGE); boolean isNew = false; if (retval != 0) { // yes. Point to it and make the next of that page the // new first free page. header.setFirstOf(Magic.FREE_PAGE, getNext(retval)); } else { // nope. make a new record retval = header.getLastOf(Magic.FREE_PAGE); if (retval == 0) // very new file - allocate record #1 retval = 1; header.setLastOf(Magic.FREE_PAGE, retval + 1); isNew = true; } // Cool. We have a record, add it to the correct list BlockIo buf = file.get(retval); PageHeader pageHdr = isNew ? new PageHeader(buf, type) : PageHeader.getView(buf); long oldLast = header.getLastOf(type); // Clean data. System.arraycopy(RecordFile.cleanData, 0, buf.getData(), 0, RecordFile.BLOCK_SIZE); pageHdr.setType(type); pageHdr.setPrev(oldLast); pageHdr.setNext(0); if (oldLast == 0) // This was the first one of this type header.setFirstOf(type, retval); header.setLastOf(type, retval); file.release(retval, true); // If there's a previous, fix up its pointer if (oldLast != 0) { buf = file.get(oldLast); pageHdr = PageHeader.getView(buf); pageHdr.setNext(retval); file.release(oldLast, true); } // remove the view, we have modified the type. buf.setView(null); return retval; } /** * Frees a page of the indicated type. */ void free(short type, long recid) throws IOException { if (type == Magic.FREE_PAGE) throw new Error("free free page?"); if (recid == 0) throw new Error("free header page?"); // get the page and read next and previous pointers BlockIo buf = file.get(recid); PageHeader pageHdr = PageHeader.getView(buf); long prev = pageHdr.getPrev(); long next = pageHdr.getNext(); // put the page at the front of the free list. pageHdr.setType(Magic.FREE_PAGE); pageHdr.setNext(header.getFirstOf(Magic.FREE_PAGE)); pageHdr.setPrev(0); header.setFirstOf(Magic.FREE_PAGE, recid); file.release(recid, true); // remove the page from its old list if (prev != 0) { buf = file.get(prev); pageHdr = PageHeader.getView(buf); pageHdr.setNext(next); file.release(prev, true); } else { header.setFirstOf(type, next); } if (next != 0) { buf = file.get(next); pageHdr = PageHeader.getView(buf); pageHdr.setPrev(prev); file.release(next, true); } else { header.setLastOf(type, prev); } } /** * Returns the page following the indicated block */ long getNext(long block) throws IOException { try { return PageHeader.getView(file.get(block)).getNext(); } finally { file.release(block, false); } } /** * Returns the page before the indicated block */ long getPrev(long block) throws IOException { try { return PageHeader.getView(file.get(block)).getPrev(); } finally { file.release(block, false); } } /** * Returns the first page on the indicated list. */ long getFirst(short type) throws IOException { return header.getFirstOf(type); } /** * Returns the last page on the indicated list. */ long getLast(short type) throws IOException { return header.getLastOf(type); } /** * Commit all pending (in-memory) data by flushing the page manager. * This forces a flush of all outstanding blocks (this it's an implicit * {@link RecordFile#commit} as well). */ void commit() throws IOException { // write the header out file.release(headerBuf); file.commit(); // and obtain it again headerBuf = file.get(0); header = new FileHeader(headerBuf, false); } /** * Flushes the page manager. This forces a flush of all outstanding * blocks (this it's an implicit {@link RecordFile#commit} as well). */ void rollback() throws IOException { // release header file.discard(headerBuf); file.rollback(); // and obtain it again headerBuf = file.get(0); if (headerBuf.readShort(0) == 0) header = new FileHeader(headerBuf, true); else header = new FileHeader(headerBuf, false); } /** * Closes the page manager. This flushes the page manager and releases * the lock on the header. */ void close() throws IOException { file.release(headerBuf); file.commit(); headerBuf = null; header = null; file = null; } /** * Returns the file header. */ FileHeader getFileHeader() { return header; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/PhysicalRowId.java0000644000175000017500000000644010276576000024060 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: PhysicalRowId.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * A physical rowid is nothing else than a pointer to a physical location * in a file - a (block, offset) tuple. *

* Note: The fact that the offset is modelled as a short limits * the block size to 32k. */ class PhysicalRowId { // offsets private static final short O_BLOCK = 0; // long block private static final short O_OFFSET = Magic.SZ_LONG; // short offset static final int SIZE = O_OFFSET + Magic.SZ_SHORT; // my block and the position within the block BlockIo block; short pos; /** * Constructs a physical rowid from the indicated data starting at * the indicated position. */ PhysicalRowId(BlockIo block, short pos) { this.block = block; this.pos = pos; } /** Returns the block number */ long getBlock() { return block.readLong(pos + O_BLOCK); } /** Sets the block number */ void setBlock(long value) { block.writeLong(pos + O_BLOCK, value); } /** Returns the offset */ short getOffset() { return block.readShort(pos + O_OFFSET); } /** Sets the offset */ void setOffset(short value) { block.writeShort(pos + O_OFFSET, value); } } libjdbm-java-1.0.orig/src/main/jdbm/recman/PhysicalRowIdManager.java0000644000175000017500000002755510276576000025365 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: PhysicalRowIdManager.java,v 1.3 2003/03/21 03:00:09 boisvert Exp $ */ package jdbm.recman; import java.io.IOException; /** * This class manages physical row ids, and their data. */ final class PhysicalRowIdManager { // The file we're talking to and the associated page manager. private RecordFile file; private PageManager pageman; private FreePhysicalRowIdPageManager freeman; /** * Creates a new rowid manager using the indicated record file. * and page manager. */ PhysicalRowIdManager( RecordFile file, PageManager pageManager ) throws IOException { this.file = file; this.pageman = pageManager; this.freeman = new FreePhysicalRowIdPageManager(file, pageman); } /** * Inserts a new record. Returns the new physical rowid. */ Location insert( byte[] data, int start, int length ) throws IOException { Location retval = alloc( length ); write( retval, data, start, length ); return retval; } /** * Updates an existing record. Returns the possibly changed * physical rowid. */ Location update( Location rowid, byte[] data, int start, int length ) throws IOException { // fetch the record header BlockIo block = file.get( rowid.getBlock() ); RecordHeader head = new RecordHeader( block, rowid.getOffset() ); if ( length > head.getAvailableSize() ) { // not enough space - we need to copy to a new rowid. file.release( block ); free( rowid ); rowid = alloc( length ); } else { file.release( block ); } // 'nuff space, write it in and return the rowid. write( rowid, data, start, length ); return rowid; } /** * Deletes a record. */ void delete( Location rowid ) throws IOException { free( rowid ); } /** * Retrieves a record. */ byte[] fetch( Location rowid ) throws IOException { // fetch the record header PageCursor curs = new PageCursor( pageman, rowid.getBlock() ); BlockIo block = file.get( curs.getCurrent() ); RecordHeader head = new RecordHeader( block, rowid.getOffset() ); // allocate a return buffer byte[] retval = new byte[ head.getCurrentSize() ]; if ( retval.length == 0 ) { file.release( curs.getCurrent(), false ); return retval; } // copy bytes in int offsetInBuffer = 0; int leftToRead = retval.length; short dataOffset = (short) (rowid.getOffset() + RecordHeader.SIZE); while ( leftToRead > 0 ) { // copy current page's data to return buffer int toCopy = RecordFile.BLOCK_SIZE - dataOffset; if ( leftToRead < toCopy ) { toCopy = leftToRead; } System.arraycopy( block.getData(), dataOffset, retval, offsetInBuffer, toCopy ); // Go to the next block leftToRead -= toCopy; offsetInBuffer += toCopy; file.release( block ); if ( leftToRead > 0 ) { block = file.get( curs.next() ); dataOffset = DataPage.O_DATA; } } return retval; } /** * Allocate a new rowid with the indicated size. */ private Location alloc( int size ) throws IOException { Location retval = freeman.get( size ); if ( retval == null ) { retval = allocNew( size, pageman.getLast( Magic.USED_PAGE ) ); } return retval; } /** * Allocates a new rowid. The second parameter is there to * allow for a recursive call - it indicates where the search * should start. */ private Location allocNew( int size, long start ) throws IOException { BlockIo curBlock; DataPage curPage; if ( start == 0 ) { // we need to create a new page. start = pageman.allocate( Magic.USED_PAGE ); curBlock = file.get( start ); curPage = DataPage.getDataPageView( curBlock ); curPage.setFirst( DataPage.O_DATA ); RecordHeader hdr = new RecordHeader( curBlock, DataPage.O_DATA ); hdr.setAvailableSize( 0 ); hdr.setCurrentSize( 0 ); } else { curBlock = file.get( start ); curPage = DataPage.getDataPageView( curBlock ); } // follow the rowids on this page to get to the last one. We don't // fall off, because this is the last page, remember? short pos = curPage.getFirst(); if ( pos == 0 ) { // page is exactly filled by the last block of a record file.release( curBlock ); return allocNew( size, 0 ); } RecordHeader hdr = new RecordHeader( curBlock, pos ); while ( hdr.getAvailableSize() != 0 && pos < RecordFile.BLOCK_SIZE ) { pos += hdr.getAvailableSize() + RecordHeader.SIZE; if ( pos == RecordFile.BLOCK_SIZE ) { // Again, a filled page. file.release( curBlock ); return allocNew( size, 0 ); } hdr = new RecordHeader( curBlock, pos ); } if ( pos == RecordHeader.SIZE ) { // the last record exactly filled the page. Restart forcing // a new page. file.release( curBlock ); } // we have the position, now tack on extra pages until we've got // enough space. Location retval = new Location( start, pos ); int freeHere = RecordFile.BLOCK_SIZE - pos - RecordHeader.SIZE; if ( freeHere < size ) { // check whether the last page would have only a small bit left. // if yes, increase the allocation. A small bit is a record // header plus 16 bytes. int lastSize = (size - freeHere) % DataPage.DATA_PER_PAGE; if (( DataPage.DATA_PER_PAGE - lastSize ) < (RecordHeader.SIZE + 16) ) { size += (DataPage.DATA_PER_PAGE - lastSize); } // write out the header now so we don't have to come back. hdr.setAvailableSize( size ); file.release( start, true ); int neededLeft = size - freeHere; // Refactor these two blocks! while ( neededLeft >= DataPage.DATA_PER_PAGE ) { start = pageman.allocate( Magic.USED_PAGE ); curBlock = file.get( start ); curPage = DataPage.getDataPageView( curBlock ); curPage.setFirst( (short) 0 ); // no rowids, just data file.release( start, true ); neededLeft -= DataPage.DATA_PER_PAGE; } if ( neededLeft > 0 ) { // done with whole chunks, allocate last fragment. start = pageman.allocate( Magic.USED_PAGE ); curBlock = file.get( start ); curPage = DataPage.getDataPageView( curBlock ); curPage.setFirst( (short) (DataPage.O_DATA + neededLeft) ); file.release( start, true ); } } else { // just update the current page. If there's less than 16 bytes // left, we increase the allocation (16 bytes is an arbitrary // number). if ( freeHere - size <= (16 + RecordHeader.SIZE) ) { size = freeHere; } hdr.setAvailableSize( size ); file.release( start, true ); } return retval; } private void free( Location id ) throws IOException { // get the rowid, and write a zero current size into it. BlockIo curBlock = file.get( id.getBlock() ); DataPage curPage = DataPage.getDataPageView( curBlock ); RecordHeader hdr = new RecordHeader( curBlock, id.getOffset() ); hdr.setCurrentSize( 0 ); file.release( id.getBlock(), true ); // write the rowid to the free list freeman.put( id, hdr.getAvailableSize() ); } /** * Writes out data to a rowid. Assumes that any resizing has been * done. */ private void write(Location rowid, byte[] data, int start, int length ) throws IOException { PageCursor curs = new PageCursor( pageman, rowid.getBlock() ); BlockIo block = file.get( curs.getCurrent() ); RecordHeader hdr = new RecordHeader( block, rowid.getOffset() ); hdr.setCurrentSize( length ); if ( length == 0 ) { file.release( curs.getCurrent(), true ); return; } // copy bytes in int offsetInBuffer = start; int leftToWrite = length; short dataOffset = (short) (rowid.getOffset() + RecordHeader.SIZE); while ( leftToWrite > 0 ) { // copy current page's data to return buffer int toCopy = RecordFile.BLOCK_SIZE - dataOffset; if ( leftToWrite < toCopy ) { toCopy = leftToWrite; } System.arraycopy( data, offsetInBuffer, block.getData(), dataOffset, toCopy ); // Go to the next block leftToWrite -= toCopy; offsetInBuffer += toCopy; file.release( curs.getCurrent(), true ); if ( leftToWrite > 0 ) { block = file.get( curs.next() ); dataOffset = DataPage.O_DATA; } } } } libjdbm-java-1.0.orig/src/main/jdbm/recman/Provider.java0000644000175000017500000001120010276576000023117 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: Provider.java,v 1.3 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.IOException; import java.util.Properties; import jdbm.RecordManager; import jdbm.RecordManagerOptions; import jdbm.RecordManagerProvider; import jdbm.helper.MRU; /** * Provider of the default RecordManager implementation. * * @author Alex Boisvert * @version $Id: Provider.java,v 1.3 2005/06/25 23:12:32 doomdark Exp $ */ public final class Provider implements RecordManagerProvider { /** * Create a default implementation record manager. * * @param name Name of the record file. * @param options Record manager options. * @throws IOException if an I/O related exception occurs while creating * or opening the record manager. * @throws UnsupportedOperationException if some options are not supported by the * implementation. * @throws IllegalArgumentException if some options are invalid. */ public RecordManager createRecordManager( String name, Properties options ) throws IOException { RecordManager recman; String value; int cacheSize; recman = new BaseRecordManager( name ); value = options.getProperty( RecordManagerOptions.DISABLE_TRANSACTIONS, "false" ); if ( value.equalsIgnoreCase( "TRUE" ) ) { ( (BaseRecordManager) recman ).disableTransactions(); } value = options.getProperty( RecordManagerOptions.CACHE_SIZE, "1000" ); cacheSize = Integer.parseInt( value ); value = options.getProperty( RecordManagerOptions.CACHE_TYPE, RecordManagerOptions.NORMAL_CACHE ); if ( value.equalsIgnoreCase( RecordManagerOptions.NORMAL_CACHE ) ) { MRU cache = new MRU( cacheSize ); recman = new CacheRecordManager( recman, cache ); } else if ( value.equalsIgnoreCase( RecordManagerOptions.SOFT_REF_CACHE ) ) { throw new IllegalArgumentException( "Soft reference cache not implemented" ); } else if ( value.equalsIgnoreCase( RecordManagerOptions.WEAK_REF_CACHE ) ) { throw new IllegalArgumentException( "Weak reference cache not implemented" ); } else { throw new IllegalArgumentException( "Invalid cache type: " + value ); } return recman; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/RecordCache.java0000644000175000017500000000547110276576000023504 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordCache.java,v 1.2 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.IOException; /** * This interface is used for synchronization. *

* RecordManager ensures that the cache has the up-to-date information * by way of an invalidation protocol. */ public interface RecordCache { /** * Notification to flush content related to a given record. */ public void flush(long recid) throws IOException; /** * Notification to flush data all of records. */ public void flushAll() throws IOException; /** * Notification to invalidate content related to given record. */ public void invalidate(long recid) throws IOException; /** * Notification to invalidate content of all records. */ public void invalidateAll() throws IOException; } libjdbm-java-1.0.orig/src/main/jdbm/recman/RecordFile.java0000644000175000017500000003111410276576000023351 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordFile.java,v 1.6 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.*; import java.util.*; /** * This class represents a random access file as a set of fixed size * records. Each record has a physical record number, and records are * cached in order to improve access. *

* The set of dirty records on the in-use list constitutes a transaction. * Later on, we will send these records to some recovery thingy. */ public final class RecordFile { final TransactionManager txnMgr; // Todo: reorganize in hashes and fifos as necessary. // free -> inUse -> dirty -> inTxn -> free // free is a cache, thus a FIFO. The rest are hashes. private final LinkedList free = new LinkedList(); private final HashMap inUse = new HashMap(); private final HashMap dirty = new HashMap(); private final HashMap inTxn = new HashMap(); // transactions disabled? private boolean transactionsDisabled = false; /** The length of a single block. */ public final static int BLOCK_SIZE = 8192;//4096; /** The extension of a record file */ final static String extension = ".db"; /** A block of clean data to wipe clean pages. */ final static byte[] cleanData = new byte[BLOCK_SIZE]; private RandomAccessFile file; private final String fileName; /** * Creates a new object on the indicated filename. The file is * opened in read/write mode. * * @param fileName the name of the file to open or create, without * an extension. * @throws IOException whenever the creation of the underlying * RandomAccessFile throws it. */ RecordFile(String fileName) throws IOException { this.fileName = fileName; file = new RandomAccessFile(fileName + extension, "rw"); txnMgr = new TransactionManager(this); } /** * Returns the file name. */ String getFileName() { return fileName; } /** * Disables transactions: doesn't sync and doesn't use the * transaction manager. */ void disableTransactions() { transactionsDisabled = true; } /** * Gets a block from the file. The returned byte array is * the in-memory copy of the record, and thus can be written * (and subsequently released with a dirty flag in order to * write the block back). * * @param blockid The record number to retrieve. */ BlockIo get(long blockid) throws IOException { Long key = new Long(blockid); // try in transaction list, dirty list, free list BlockIo node = (BlockIo) inTxn.get(key); if (node != null) { inTxn.remove(key); inUse.put(key, node); return node; } node = (BlockIo) dirty.get(key); if (node != null) { dirty.remove(key); inUse.put(key, node); return node; } for (Iterator i = free.iterator(); i.hasNext(); ) { BlockIo cur = (BlockIo) i.next(); if (cur.getBlockId() == blockid) { node = cur; i.remove(); inUse.put(key, node); return node; } } // sanity check: can't be on in use list if (inUse.get(key) != null) { throw new Error("double get for block " + blockid); } // get a new node and read it from the file node = getNewNode(blockid); long offset = blockid * BLOCK_SIZE; if (file.length() > 0 && offset <= file.length()) { read(file, offset, node.getData(), BLOCK_SIZE); } else { System.arraycopy(cleanData, 0, node.getData(), 0, BLOCK_SIZE); } inUse.put(key, node); node.setClean(); return node; } /** * Releases a block. * * @param blockid The record number to release. * @param isDirty If true, the block was modified since the get(). */ void release(long blockid, boolean isDirty) throws IOException { BlockIo node = (BlockIo) inUse.get(new Long(blockid)); if (node == null) throw new IOException("bad blockid " + blockid + " on release"); if (!node.isDirty() && isDirty) node.setDirty(); release(node); } /** * Releases a block. * * @param block The block to release. */ void release(BlockIo block) { Long key = new Long(block.getBlockId()); inUse.remove(key); if (block.isDirty()) { // System.out.println( "Dirty: " + key + block ); dirty.put(key, block); } else { if (!transactionsDisabled && block.isInTransaction()) { inTxn.put(key, block); } else { free.add(block); } } } /** * Discards a block (will not write the block even if it's dirty) * * @param block The block to discard. */ void discard(BlockIo block) { Long key = new Long(block.getBlockId()); inUse.remove(key); // note: block not added to free list on purpose, because // it's considered invalid } /** * Commits the current transaction by flushing all dirty buffers * to disk. */ void commit() throws IOException { // debugging... if (!inUse.isEmpty() && inUse.size() > 1) { showList(inUse.values().iterator()); throw new Error("in use list not empty at commit time (" + inUse.size() + ")"); } // System.out.println("committing..."); if ( dirty.size() == 0 ) { // if no dirty blocks, skip commit process return; } if (!transactionsDisabled) { txnMgr.start(); } for (Iterator i = dirty.values().iterator(); i.hasNext(); ) { BlockIo node = (BlockIo) i.next(); i.remove(); // System.out.println("node " + node + " map size now " + dirty.size()); if (transactionsDisabled) { long offset = node.getBlockId() * BLOCK_SIZE; file.seek(offset); file.write(node.getData()); node.setClean(); free.add(node); } else { txnMgr.add(node); inTxn.put(new Long(node.getBlockId()), node); } } if (!transactionsDisabled) { txnMgr.commit(); } } /** * Rollback the current transaction by discarding all dirty buffers */ void rollback() throws IOException { // debugging... if (!inUse.isEmpty()) { showList(inUse.values().iterator()); throw new Error("in use list not empty at rollback time (" + inUse.size() + ")"); } // System.out.println("rollback..."); dirty.clear(); txnMgr.synchronizeLogFromDisk(); if (!inTxn.isEmpty()) { showList(inTxn.values().iterator()); throw new Error("in txn list not empty at rollback time (" + inTxn.size() + ")"); }; } /** * Commits and closes file. */ void close() throws IOException { if (!dirty.isEmpty()) { commit(); } txnMgr.shutdown(); if (!inTxn.isEmpty()) { showList(inTxn.values().iterator()); throw new Error("In transaction not empty"); } // these actually ain't that bad in a production release if (!dirty.isEmpty()) { System.out.println("ERROR: dirty blocks at close time"); showList(dirty.values().iterator()); throw new Error("Dirty blocks at close time"); } if (!inUse.isEmpty()) { System.out.println("ERROR: inUse blocks at close time"); showList(inUse.values().iterator()); throw new Error("inUse blocks at close time"); } // debugging stuff to keep an eye on the free list // System.out.println("Free list size:" + free.size()); file.close(); file = null; } /** * Force closing the file and underlying transaction manager. * Used for testing purposed only. */ void forceClose() throws IOException { txnMgr.forceClose(); file.close(); } /** * Prints contents of a list */ private void showList(Iterator i) { int cnt = 0; while (i.hasNext()) { System.out.println("elem " + cnt + ": " + i.next()); cnt++; } } /** * Returns a new node. The node is retrieved (and removed) * from the released list or created new. */ private BlockIo getNewNode(long blockid) throws IOException { BlockIo retval = null; if (!free.isEmpty()) { retval = (BlockIo) free.removeFirst(); } if (retval == null) retval = new BlockIo(0, new byte[BLOCK_SIZE]); retval.setBlockId(blockid); retval.setView(null); return retval; } /** * Synchs a node to disk. This is called by the transaction manager's * synchronization code. */ void synch(BlockIo node) throws IOException { byte[] data = node.getData(); if (data != null) { long offset = node.getBlockId() * BLOCK_SIZE; file.seek(offset); file.write(data); } } /** * Releases a node from the transaction list, if it was sitting * there. * * @param recycle true if block data can be reused */ void releaseFromTransaction(BlockIo node, boolean recycle) throws IOException { Long key = new Long(node.getBlockId()); if ((inTxn.remove(key) != null) && recycle) { free.add(node); } } /** * Synchronizes the file. */ void sync() throws IOException { file.getFD().sync(); } /** * Utility method: Read a block from a RandomAccessFile */ private static void read(RandomAccessFile file, long offset, byte[] buffer, int nBytes) throws IOException { file.seek(offset); int remaining = nBytes; int pos = 0; while (remaining > 0) { int read = file.read(buffer, pos, remaining); if (read == -1) { System.arraycopy(cleanData, 0, buffer, pos, remaining); break; } remaining -= read; pos += read; } } } libjdbm-java-1.0.orig/src/main/jdbm/recman/RecordHeader.java0000644000175000017500000000763410276576000023674 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordHeader.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * The data that comes at the start of a record of data. It stores * both the current size and the avaliable size for the record - the latter * can be bigger than the former, which allows the record to grow without * needing to be moved and which allows the system to put small records * in larger free spots. */ class RecordHeader { // offsets private static final short O_CURRENTSIZE = 0; // int currentSize private static final short O_AVAILABLESIZE = Magic.SZ_INT; // int availableSize static final int SIZE = O_AVAILABLESIZE + Magic.SZ_INT; // my block and the position within the block private BlockIo block; private short pos; /** * Constructs a record header from the indicated data starting at * the indicated position. */ RecordHeader(BlockIo block, short pos) { this.block = block; this.pos = pos; if (pos > (RecordFile.BLOCK_SIZE - SIZE)) throw new Error("Offset too large for record header (" + block.getBlockId() + ":" + pos + ")"); } /** Returns the current size */ int getCurrentSize() { return block.readInt(pos + O_CURRENTSIZE); } /** Sets the current size */ void setCurrentSize(int value) { block.writeInt(pos + O_CURRENTSIZE, value); } /** Returns the available size */ int getAvailableSize() { return block.readInt(pos + O_AVAILABLESIZE); } /** Sets the available size */ void setAvailableSize(int value) { block.writeInt(pos + O_AVAILABLESIZE, value); } // overrides java.lang.Object public String toString() { return "RH(" + block.getBlockId() + ":" + pos + ", avl=" + getAvailableSize() + ", cur=" + getCurrentSize() + ")"; } } libjdbm-java-1.0.orig/src/main/jdbm/recman/TransactionManager.java0000644000175000017500000003063210276576000025117 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: TransactionManager.java,v 1.7 2005/06/25 23:12:32 doomdark Exp $ */ package jdbm.recman; import java.io.*; import java.util.*; /** * This class manages the transaction log that belongs to every * {@link RecordFile}. The transaction log is either clean, or * in progress. In the latter case, the transaction manager * takes care of a roll forward. *

* Implementation note: this is a proof-of-concept implementation * which hasn't been optimized for speed. For instance, all sorts * of streams are created for every transaction. */ // TODO: Handle the case where we are recovering lg9 and lg0, were we // should start with lg9 instead of lg0! public final class TransactionManager { private RecordFile owner; // streams for transaction log. private FileOutputStream fos; private ObjectOutputStream oos; /** * By default, we keep 10 transactions in the log file before * synchronizing it with the main database file. */ static final int DEFAULT_TXNS_IN_LOG = 10; /** * Maximum number of transactions before the log file is * synchronized with the main database file. */ private int _maxTxns = DEFAULT_TXNS_IN_LOG; /** * In-core copy of transactions. We could read everything back from * the log file, but the RecordFile needs to keep the dirty blocks in * core anyway, so we might as well point to them and spare us a lot * of hassle. */ private ArrayList[] txns = new ArrayList[DEFAULT_TXNS_IN_LOG]; private int curTxn = -1; /** Extension of a log file. */ static final String extension = ".lg"; /** * Instantiates a transaction manager instance. If recovery * needs to be performed, it is done. * * @param owner the RecordFile instance that owns this transaction mgr. */ TransactionManager(RecordFile owner) throws IOException { this.owner = owner; recover(); open(); } /** * Synchronize log file data with the main database file. *

* After this call, the main database file is guaranteed to be * consistent and guaranteed to be the only file needed for * backup purposes. */ public void synchronizeLog() throws IOException { synchronizeLogFromMemory(); } /** * Set the maximum number of transactions to record in * the log (and keep in memory) before the log is * synchronized with the main database file. *

* This method must be called while there are no * pending transactions in the log. */ public void setMaximumTransactionsInLog( int maxTxns ) throws IOException { if ( maxTxns <= 0 ) { throw new IllegalArgumentException( "Argument 'maxTxns' must be greater than 0." ); } if ( curTxn != -1 ) { throw new IllegalStateException( "Cannot change setting while transactions are pending in the log" ); } _maxTxns = maxTxns; txns = new ArrayList[ maxTxns ]; } /** Builds logfile name */ private String makeLogName() { return owner.getFileName() + extension; } /** Synchs in-core transactions to data file and opens a fresh log */ private void synchronizeLogFromMemory() throws IOException { close(); TreeSet blockList = new TreeSet( new BlockIoComparator() ); int numBlocks = 0; int writtenBlocks = 0; for (int i = 0; i < _maxTxns; i++) { if (txns[i] == null) continue; // Add each block to the blockList, replacing the old copy of this // block if necessary, thus avoiding writing the same block twice for (Iterator k = txns[i].iterator(); k.hasNext(); ) { BlockIo block = (BlockIo)k.next(); if ( blockList.contains( block ) ) { block.decrementTransactionCount(); } else { writtenBlocks++; boolean result = blockList.add( block ); } numBlocks++; } txns[i] = null; } // Write the blocks from the blockList to disk synchronizeBlocks(blockList.iterator(), true); owner.sync(); open(); } /** Opens the log file */ private void open() throws IOException { fos = new FileOutputStream(makeLogName()); oos = new ObjectOutputStream(fos); oos.writeShort(Magic.LOGFILE_HEADER); oos.flush(); curTxn = -1; } /** Startup recovery on all files */ private void recover() throws IOException { String logName = makeLogName(); File logFile = new File(logName); if (!logFile.exists()) return; if (logFile.length() == 0) { logFile.delete(); return; } FileInputStream fis = new FileInputStream(logFile); ObjectInputStream ois = new ObjectInputStream(fis); try { if (ois.readShort() != Magic.LOGFILE_HEADER) throw new Error("Bad magic on log file"); } catch (IOException e) { // corrupted/empty logfile logFile.delete(); return; } while (true) { ArrayList blocks = null; try { blocks = (ArrayList) ois.readObject(); } catch (ClassNotFoundException e) { throw new Error("Unexcepted exception: " + e); } catch (IOException e) { // corrupted logfile, ignore rest of transactions break; } synchronizeBlocks(blocks.iterator(), false); // ObjectInputStream must match exactly each // ObjectOutputStream created during writes try { ois = new ObjectInputStream(fis); } catch (IOException e) { // corrupted logfile, ignore rest of transactions break; } } owner.sync(); logFile.delete(); } /** Synchronizes the indicated blocks with the owner. */ private void synchronizeBlocks(Iterator blockIterator, boolean fromCore) throws IOException { // write block vector elements to the data file. while ( blockIterator.hasNext() ) { BlockIo cur = (BlockIo)blockIterator.next(); owner.synch(cur); if (fromCore) { cur.decrementTransactionCount(); if (!cur.isInTransaction()) { owner.releaseFromTransaction(cur, true); } } } } /** Set clean flag on the blocks. */ private void setClean(ArrayList blocks) throws IOException { for (Iterator k = blocks.iterator(); k.hasNext(); ) { BlockIo cur = (BlockIo) k.next(); cur.setClean(); } } /** Discards the indicated blocks and notify the owner. */ private void discardBlocks(ArrayList blocks) throws IOException { for (Iterator k = blocks.iterator(); k.hasNext(); ) { BlockIo cur = (BlockIo) k.next(); cur.decrementTransactionCount(); if (!cur.isInTransaction()) { owner.releaseFromTransaction(cur, false); } } } /** * Starts a transaction. This can block if all slots have been filled * with full transactions, waiting for the synchronization thread to * clean out slots. */ void start() throws IOException { curTxn++; if (curTxn == _maxTxns) { synchronizeLogFromMemory(); curTxn = 0; } txns[curTxn] = new ArrayList(); } /** * Indicates the block is part of the transaction. */ void add(BlockIo block) throws IOException { block.incrementTransactionCount(); txns[curTxn].add(block); } /** * Commits the transaction to the log file. */ void commit() throws IOException { oos.writeObject(txns[curTxn]); sync(); // set clean flag to indicate blocks have been written to log setClean(txns[curTxn]); // open a new ObjectOutputStream in order to store // newer states of BlockIo oos = new ObjectOutputStream(fos); } /** Flushes and syncs */ private void sync() throws IOException { oos.flush(); fos.flush(); fos.getFD().sync(); } /** * Shutdowns the transaction manager. Resynchronizes outstanding * logs. */ void shutdown() throws IOException { synchronizeLogFromMemory(); close(); } /** * Closes open files. */ private void close() throws IOException { sync(); oos.close(); fos.close(); oos = null; fos = null; } /** * Force closing the file without synchronizing pending transaction data. * Used for testing purposes only. */ void forceClose() throws IOException { oos.close(); fos.close(); oos = null; fos = null; } /** * Use the disk-based transaction log to synchronize the data file. * Outstanding memory logs are discarded because they are believed * to be inconsistent. */ void synchronizeLogFromDisk() throws IOException { close(); for ( int i=0; i < _maxTxns; i++ ) { if (txns[i] == null) continue; discardBlocks(txns[i]); txns[i] = null; } recover(); open(); } /** INNER CLASS. * Comparator class for use by the tree set used to store the blocks * to write for this transaction. The BlockIo objects are ordered by * their blockIds. */ public static class BlockIoComparator implements Comparator { public int compare( Object o1, Object o2 ) { BlockIo block1 = (BlockIo)o1; BlockIo block2 = (BlockIo)o2; int result = 0; if ( block1.getBlockId() == block2.getBlockId() ) { result = 0; } else if ( block1.getBlockId() < block2.getBlockId() ) { result = -1; } else { result = 1; } return result; } public boolean equals(Object obj) { return super.equals(obj); } } // class BlockIOComparator } libjdbm-java-1.0.orig/src/main/jdbm/recman/TranslationPage.java0000644000175000017500000000671110276576000024433 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: TranslationPage.java,v 1.1 2000/05/06 00:00:31 boisvert Exp $ */ package jdbm.recman; /** * Class describing a page that holds translations from physical rowids * to logical rowids. In fact, the page just holds physical rowids - the * page's block is the block for the logical rowid, the offset serve * as offset for the rowids. */ final class TranslationPage extends PageHeader { // offsets static final short O_TRANS = PageHeader.SIZE; // short count static final short ELEMS_PER_PAGE = (RecordFile.BLOCK_SIZE - O_TRANS) / PhysicalRowId.SIZE; // slots we returned. final PhysicalRowId[] slots = new PhysicalRowId[ELEMS_PER_PAGE]; /** * Constructs a data page view from the indicated block. */ TranslationPage(BlockIo block) { super(block); } /** * Factory method to create or return a data page for the * indicated block. */ static TranslationPage getTranslationPageView(BlockIo block) { BlockView view = block.getView(); if (view != null && view instanceof TranslationPage) return (TranslationPage) view; else return new TranslationPage(block); } /** Returns the value of the indicated rowid on the page */ PhysicalRowId get(short offset) { int slot = (offset - O_TRANS) / PhysicalRowId.SIZE; if (slots[slot] == null) slots[slot] = new PhysicalRowId(block, offset); return slots[slot]; } } libjdbm-java-1.0.orig/src/main/jdbm/package.html0000644000175000017500000000131510276576000021504 0ustar twernertwerner

Simplified public API corresponding to GDBM APIs.

JDBM

JDBM is a simple transactional persistent engine for Java. It aims to be for Java what GDBM is for C/C++, Perl, Python, etc: a fast, simple persistence engine.

You can use it to store a mix of hashtables and blobs, and all updates are done in a transactionally safe manner.

Version:
$Revision: 1.1 $ $Date: 2001/05/19 16:01:32 $
Author:
Alex Boisvert
libjdbm-java-1.0.orig/src/main/jdbm/RecordManager.java0000644000175000017500000001632210276576000022603 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordManager.java,v 1.3 2005/06/25 23:12:31 doomdark Exp $ */ package jdbm; import java.io.IOException; import jdbm.helper.Serializer; /** * An interface to manages records, which are uninterpreted blobs of data. *

* The set of record operations is simple: fetch, insert, update and delete. * Each record is identified using a "rowid" and contains a byte[] data block. * Rowids are returned on inserts and you can store them someplace safe * to be able to get back to them. Data blocks can be as long as you wish, * and may have lengths different from the original when updating. * * @author Alex Boisvert * @author Cees de Groot * @version $Id: RecordManager.java,v 1.3 2005/06/25 23:12:31 doomdark Exp $ */ public interface RecordManager { /** * Reserved slot for name directory. */ public static final int NAME_DIRECTORY_ROOT = 0; /** * Inserts a new record using standard java object serialization. * * @param obj the object for the new record. * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public abstract long insert( Object obj ) throws IOException; /** * Inserts a new record using a custom serializer. * * @param obj the object for the new record. * @param serializer a custom serializer * @return the rowid for the new record. * @throws IOException when one of the underlying I/O operations fails. */ public abstract long insert( Object obj, Serializer serializer ) throws IOException; /** * Deletes a record. * * @param recid the rowid for the record that should be deleted. * @throws IOException when one of the underlying I/O operations fails. */ public abstract void delete( long recid ) throws IOException; /** * Updates a record using standard java object serialization. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @throws IOException when one of the underlying I/O operations fails. */ public abstract void update( long recid, Object obj ) throws IOException; /** * Updates a record using a custom serializer. * * @param recid the recid for the record that is to be updated. * @param obj the new object for the record. * @param serializer a custom serializer * @throws IOException when one of the underlying I/O operations fails. */ public abstract void update( long recid, Object obj, Serializer serializer ) throws IOException; /** * Fetches a record using standard java object serialization. * * @param recid the recid for the record that must be fetched. * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public abstract Object fetch( long recid ) throws IOException; /** * Fetches a record using a custom serializer. * * @param recid the recid for the record that must be fetched. * @param serializer a custom serializer * @return the object contained in the record. * @throws IOException when one of the underlying I/O operations fails. */ public abstract Object fetch( long recid, Serializer serializer ) throws IOException; /** * Closes the record manager. * * @throws IOException when one of the underlying I/O operations fails. */ public abstract void close() throws IOException; /** * Returns the number of slots available for "root" rowids. These slots * can be used to store special rowids, like rowids that point to * other rowids. Root rowids are useful for bootstrapping access to * a set of data. */ public abstract int getRootCount(); /** * Returns the indicated root rowid. * * @see #getRootCount */ public abstract long getRoot( int id ) throws IOException; /** * Sets the indicated root rowid. * * @see #getRootCount */ public abstract void setRoot( int id, long rowid ) throws IOException; /** * Commit (make persistent) all changes since beginning of transaction. */ public abstract void commit() throws IOException; /** * Rollback (cancel) all changes since beginning of transaction. */ public abstract void rollback() throws IOException; /** * Obtain the record id of a named object. Returns 0 if named object * doesn't exist. */ public abstract long getNamedObject( String name ) throws IOException; /** * Set the record id of a named object. */ public abstract void setNamedObject( String name, long recid ) throws IOException; } libjdbm-java-1.0.orig/src/main/jdbm/RecordManagerFactory.java0000644000175000017500000001140110276576000024124 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordManagerFactory.java,v 1.2 2005/06/25 23:12:31 doomdark Exp $ */ package jdbm; import java.io.IOException; import java.util.Properties; /** * This is the factory class to use for instantiating {@link RecordManager} * instances. * * @author Alex Boisvert * @author Cees de Groot * @version $Id: RecordManagerFactory.java,v 1.2 2005/06/25 23:12:31 doomdark Exp $ */ public final class RecordManagerFactory { /** * Create a record manager. * * @param name Name of the record file. * @throws IOException if an I/O related exception occurs while creating * or opening the record manager. * @throws UnsupportedOperationException if some options are not supported by the * implementation. * @throws IllegalArgumentException if some options are invalid. */ public static RecordManager createRecordManager( String name ) throws IOException { return createRecordManager( name, new Properties() ); } /** * Create a record manager. * * @param name Name of the record file. * @param options Record manager options. * @throws IOException if an I/O related exception occurs while creating * or opening the record manager. * @throws UnsupportedOperationException if some options are not supported by the * implementation. * @throws IllegalArgumentException if some options are invalid. */ public static RecordManager createRecordManager( String name, Properties options ) throws IOException { String provider; Class clazz; RecordManagerProvider factory; provider = options.getProperty( RecordManagerOptions.PROVIDER_FACTORY, "jdbm.recman.Provider" ); try { clazz = Class.forName( provider ); factory = (RecordManagerProvider) clazz.newInstance(); } catch ( Exception except ) { throw new IllegalArgumentException( "Invalid record manager provider: " + provider + "\n[" + except.getClass().getName() + ": " + except.getMessage() + "]" ); } return factory.createRecordManager( name, options ); } } libjdbm-java-1.0.orig/src/main/jdbm/RecordManagerOptions.java0000644000175000017500000001025410276576000024155 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordManagerOptions.java,v 1.1 2002/05/31 06:33:20 boisvert Exp $ */ package jdbm; /** * Standard options for RecordManager. * * @author Alex Boisvert * @author Cees de Groot * @version $Id: RecordManagerOptions.java,v 1.1 2002/05/31 06:33:20 boisvert Exp $ */ public class RecordManagerOptions { /** * Option to create a thread-safe record manager. */ public static final String PROVIDER_FACTORY = "jdbm.provider"; /** * Option to create a thread-safe record manager. */ public static final String THREAD_SAFE = "jdbm.threadSafe"; /** * Option to automatically commit data after each operation. */ public static final String AUTO_COMMIT = "jdbm.autoCommit"; /** * Option to disable transaction (to increase performance at the cost of * potential data loss). */ public static final String DISABLE_TRANSACTIONS = "jdbm.disableTransactions"; /** * Cache type. */ public static final String CACHE_TYPE = "jdbm.cache.type"; /** * Cache size (when applicable) */ public static final String CACHE_SIZE = "jdbm.cache.size"; /** * Use normal (strong) object references for the record cache. */ public static final String NORMAL_CACHE = "normal"; /** * Use soft references {$link java.lang.ref.SoftReference} for the record * cache instead of the default normal object references. *

* Soft references are cleared at the discretion of the garbage collector * in response to memory demand. */ public static final String SOFT_REF_CACHE = "soft"; /** * Use weak references {$link java.lang.ref.WeakReference} for the record * cache instead of the default normal object references. *

* Weak references do not prevent their referents from being made * finalizable, finalized, and then reclaimed. */ public static final String WEAK_REF_CACHE = "weak"; } libjdbm-java-1.0.orig/src/main/jdbm/RecordManagerProvider.java0000644000175000017500000000641110276576000024314 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Copyright 2000-2001 (C) Alex Boisvert. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: RecordManagerProvider.java,v 1.2 2005/06/25 23:12:31 doomdark Exp $ */ package jdbm; import java.io.IOException; import java.util.Properties; /** * Provider of RecordManager implementation. Classes implementing this * interface act as a factory to provide implementations of RecordManager. * * @author Alex Boisvert * @version $Id: RecordManagerProvider.java,v 1.2 2005/06/25 23:12:31 doomdark Exp $ */ public interface RecordManagerProvider { /** * Create a record manager. * * @param filename Base filename of the record file. * @param options Record manager options. * @throws IOException if an I/O related exception occurs while creating * or opening the record manager. * @throws UnsupportedOperationException if some options are not supported by the * implementation. * @throws IllegalArgumentException if some options are invalid. */ public RecordManager createRecordManager( String filename, Properties options ) throws IOException; } libjdbm-java-1.0.orig/src/tests/0000775000175000017500000000000010276576000016527 5ustar twernertwernerlibjdbm-java-1.0.orig/src/tests/jdbm/0000775000175000017500000000000010276576000017443 5ustar twernertwernerlibjdbm-java-1.0.orig/src/tests/jdbm/btree/0000775000175000017500000000000010276576000020544 5ustar twernertwernerlibjdbm-java-1.0.orig/src/tests/jdbm/btree/BTreeBench.java0000644000175000017500000001200210276576000023341 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.btree; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.helper.LongComparator; import java.util.Enumeration; import java.util.Hashtable; import java.io.IOException; /** * Random insertion/removal test for B+Tree data structure. * * @author Alex Boisvert * @version $Id: BTreeBench.java,v 1.5 2005/06/25 23:12:32 doomdark Exp $ */ public class BTreeBench { static final int ITERATIONS = 1000000; public static void main( String[] args ) { RecordManager recman; BTree tree = null; try { recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new LongComparator(), null, null, 32 ); Hashtable hash = new Hashtable(); for ( int i=0; i * * I tried to insert a couple of elements into a BTree and then remove * them one by one. After a number or removals, there is always (if more * than 20 elements in btree) a java.io.StreamCorruptedException thrown. * * The strange thing is, that on 50 elements, the exception is thrown * after removing 22, on 200 it is thrown after 36, on 1000 it is thrown * after 104, on 10000 it is thrown after 1003.... * * The full stackTrace is here: * ---------------------- snip ------- snap ------------------------- * java.io.StreamCorruptedException: Caught EOFException while reading the * stream header * at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:845) * at java.io.ObjectInputStream.(ObjectInputStream.java:168) * at jdbm.recman.RecordManager.byteArrayToObject(RecordManager.java:296) * at jdbm.recman.RecordManager.fetchObject(RecordManager.java:239) * at jdbm.helper.ObjectCache.fetchObject(ObjectCache.java:104) * at jdbm.btree.BPage.loadBPage(BPage.java:670) * at jdbm.btree.BPage.remove(BPage.java:492) * at jdbm.btree.BPage.remove(BPage.java:437) * at jdbm.btree.BTree.remove(BTree.java:313) * at JDBMTest.main(JDBMTest.java:41) * * * * @author Christof Dallermassl * @version $Id: StreamCorrupted.java,v 1.4 2003/09/21 15:49:02 boisvert Exp $ */ public class StreamCorrupted extends TestCase { public StreamCorrupted( String name ) { super( name ); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Basic tests */ public void testStreamCorrupted() throws IOException { RecordManager recman; BTree btree; int iterations; iterations = 100; // 23 works :-((((( // open database recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); // create a new B+Tree data structure btree = BTree.createInstance( recman, new StringComparator() ); recman.setNamedObject( "testbtree", btree.getRecid() ); // action: // insert data for( int count = 0; count < iterations; count++ ) { btree.insert( "num" + count, new Integer( count ), true ); } // delete data for( int count = 0; count < iterations; count++ ) { btree.remove( "num" + count ); } // close database recman.close(); recman = null; } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run( new TestSuite( StreamCorrupted.class ) ); } } libjdbm-java-1.0.orig/src/tests/jdbm/btree/Test.java0000644000175000017500000000531610276576000022331 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.btree; import junit.framework.*; /** * "jdbm.btree.*" package test suite * * @author Alex Boisvert * @version $Id: Test.java,v 1.2 2001/08/28 06:15:24 boisvert Exp $ */ public class Test extends TestCase { public Test(String name) { super(name); } public static junit.framework.Test suite() { TestSuite retval = new TestSuite(); retval.addTest( new TestSuite( TestBPage.class ) ); retval.addTest( new TestSuite( TestBTree.class ) ); retval.addTest( new TestSuite( StreamCorrupted.class ) ); return retval; } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } } libjdbm-java-1.0.orig/src/tests/jdbm/btree/TestBPage.java0000644000175000017500000001040010276576000023216 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.btree; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.recman.TestRecordFile; import jdbm.helper.StringComparator; import jdbm.helper.Tuple; import jdbm.helper.TupleBrowser; import java.io.IOException; import junit.framework.*; /** * This class contains all Unit tests for {@link Bpage}. * * @author Alex Boisvert * @version $Id: TestBPage.java,v 1.5 2003/09/21 15:49:02 boisvert Exp $ */ public class TestBPage extends TestCase { public TestBPage( String name ) { super( name ); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Basic tests */ public void testBasics() throws IOException { RecordManager recman; String test, test1, test2, test3; test = "test"; test1 = "test1"; test2 = "test2"; test3 = "test3"; recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); BTree tree = BTree.createInstance( recman, new StringComparator(), null, null, 32 ); BPage page = new BPage( tree, test, test ); TupleBrowser browser; Tuple tuple = new Tuple(); // test insertion page.insert( 1, test2, test2, false ); page.insert( 1, test3, test3, false ); page.insert( 1, test1, test1, false ); // test binary search browser = page.find( 1, test2 ); if ( browser.getNext( tuple ) == false ) { throw new IllegalStateException( "Browser didn't have 'test2'" ); } if ( ! tuple.getKey().equals( test2 ) ) { throw new IllegalStateException( "Tuple key is not 'test2'" ); } if ( ! tuple.getValue().equals( test2 ) ) { throw new IllegalStateException( "Tuple value is not 'test2'" ); } recman.close(); recman = null; } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run( new TestSuite( TestBPage.class ) ); } } libjdbm-java-1.0.orig/src/tests/jdbm/btree/TestBTree.java0000644000175000017500000005617110276576000023260 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.btree; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.recman.TestRecordFile; import jdbm.helper.ByteArrayComparator; import jdbm.helper.StringComparator; import jdbm.helper.TupleBrowser; import jdbm.helper.Tuple; import junit.framework.*; import java.io.IOException; import java.io.Serializable; import java.util.Map; import java.util.TreeMap; import java.util.Iterator; /** * This class contains all Unit tests for {@link BTree}. * * @author Alex Boisvert * @version $Id: TestBTree.java,v 1.8 2003/09/21 15:49:02 boisvert Exp $ */ public class TestBTree extends TestCase { static final boolean DEBUG = false; // the number of threads to be started in the synchronization test static final int THREAD_NUMBER = 5; // the size of the content of the maps for the synchronization // test. Beware that THREAD_NUMBER * THREAD_CONTENT_COUNT < Integer.MAX_VALUE. static final int THREAD_CONTENT_SIZE = 150; // for how long should the threads run. static final int THREAD_RUNTIME = 10 * 1000; protected TestResult result_; public TestBTree( String name ) { super( name ); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Overrides TestCase.run(TestResult), so the errors from threads * started from this thread can be added to the testresult. This is * shown in * http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-junit.html * * @param result the testresult */ public void run( TestResult result ) { result_ = result; super.run( result ); result_ = null; } //---------------------------------------------------------------------- /** * Handles the exceptions from other threads, so they are not ignored * in the junit test result. This method must be called from every * thread's run() method, if any throwables were throws. * * @param t the throwable (either from an assertEquals, assertTrue, * fail, ... method, or an uncaught exception to be added to the test * result of the junit test. */ protected void handleThreadException(final Throwable t) { synchronized(result_) { if(t instanceof AssertionFailedError) result_.addFailure(this,(AssertionFailedError)t); else result_.addError(this,t); } } /** * Basic tests */ public void testBasics() throws IOException { RecordManager recman; BTree tree; byte[] test, test0, test1, test2, test3; byte[] value1, value2; test = "test".getBytes(); test0 = "test0".getBytes(); test1 = "test1".getBytes(); test2 = "test2".getBytes(); test3 = "test3".getBytes(); value1 = "value1".getBytes(); value2 = "value2".getBytes(); if ( DEBUG ) { System.out.println("TestBTree.testBasics"); } recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new ByteArrayComparator() ); tree.insert( test1, value1, false ); tree.insert( test2, value2, false ); byte[] result; result = (byte[]) tree.find( test0 ); if ( result != null ) { throw new Error( "Test0 shouldn't be found" ); } result = (byte[]) tree.find( test1 ); if ( result == null || ByteArrayComparator.compareByteArray( result, value1 ) != 0 ) { throw new Error( "Invalid value for test1: " + result ); } result = (byte[]) tree.find( test2 ); if ( result == null || ByteArrayComparator.compareByteArray( result, value2 ) != 0 ) { throw new Error( "Invalid value for test2: " + result ); } result = (byte[]) tree.find( test3 ); if ( result != null ) { throw new Error( "Test3 shouldn't be found" ); } recman.close(); } /** * Basic tests, just use the simple test possibilities of junit (cdaller) */ public void testBasics2() throws IOException { RecordManager recman; BTree tree; byte[] test, test0, test1, test2, test3; byte[] value1, value2; test = "test".getBytes(); test0 = "test0".getBytes(); test1 = "test1".getBytes(); test2 = "test2".getBytes(); test3 = "test3".getBytes(); value1 = "value1".getBytes(); value2 = "value2".getBytes(); if ( DEBUG ) System.out.println("TestBTree.testBasics2"); recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new ByteArrayComparator() ); tree.insert( test1, value1, false); tree.insert( test2, value2, false); assertEquals( null, tree.find( test0 ) ); assertEquals( 0, ByteArrayComparator.compareByteArray( value1, (byte[]) tree.find( test1 ) ) ); assertEquals( 0, ByteArrayComparator.compareByteArray( value2, (byte[]) tree.find( test2 ) ) ); assertEquals( null, (byte[]) tree.find( test3 ) ); recman.close(); } /** * Test what happens after the recmanager has been closed but the * btree is accessed. WHAT SHOULD HAPPEN??????????? * (cdaller) */ public void testClose() throws IOException { RecordManager recman; BTree tree; byte[] test, test0, test1, test2, test3; byte[] value1, value2; test = "test".getBytes(); test0 = "test0".getBytes(); test1 = "test1".getBytes(); test2 = "test2".getBytes(); test3 = "test3".getBytes(); value1 = "value1".getBytes(); value2 = "value2".getBytes(); if ( DEBUG ) System.out.println("TestBTree.testClose"); recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new ByteArrayComparator() ); tree.insert( test1, value1, false ); tree.insert( test2, value2, false ); assertEquals( null, tree.find( test0 ) ); assertEquals( 0, ByteArrayComparator.compareByteArray( value1, (byte[]) tree.find( test1 ) ) ); assertEquals( 0, ByteArrayComparator.compareByteArray( value2, (byte[]) tree.find( test2 ) ) ); assertEquals( null, (byte[]) tree.find( test3 ) ); recman.close(); try { tree.browse(); fail("Should throw an IllegalStateException on access on not opened btree"); } catch( IllegalStateException except ) { // ignore } try { tree.find( test0 ); fail( "Should throw an IllegalStateException on access on not opened btree" ); } catch( IllegalStateException except ) { // ignore } try { tree.findGreaterOrEqual( test0 ); fail( "Should throw an IllegalStateException on access on not opened btree" ); } catch( IllegalStateException except ) { // ignore } try { tree.insert( test2, value2, false ); fail( "Should throw an IllegalStateException on access on not opened btree" ); } catch( IllegalStateException except ) { // ignore } try { tree.remove( test0 ); fail( "Should throw an IllegalStateException on access on not opened btree" ); } catch( IllegalStateException except ) { // ignore } /* try { tree.size(); fail( "Should throw an IllegalStateException on access on not opened btree" ); } catch( IllegalStateException except ) { // ignore } */ } /** * Test to insert different objects into one btree. (cdaller) */ public void testInsert() throws IOException { RecordManager recman; BTree tree; if ( DEBUG ) System.out.println("TestBTree.testInsert"); recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new StringComparator() ); // insert differnt objects and retrieve them tree.insert("test1", "value1",false); tree.insert("test2","value2",false); tree.insert("one", new Integer(1),false); tree.insert("two",new Long(2),false); tree.insert("myownobject",new TestObject(new Integer(234)),false); assertEquals("value2",(String)tree.find("test2")); assertEquals("value1",(String)tree.find("test1")); assertEquals(new Integer(1),(Integer)tree.find("one")); assertEquals(new Long(2),(Long)tree.find("two")); // what happens here? must not be replaced, does it return anything? // probably yes! assertEquals("value1",tree.insert("test1","value11",false)); assertEquals("value1",tree.find("test1")); // still the old value? assertEquals("value1",tree.insert("test1","value11",true)); assertEquals("value11",tree.find("test1")); // now the new value! TestObject expected_obj = new TestObject(new Integer(234)); TestObject btree_obj = (TestObject)tree.find("myownobject"); assertEquals(expected_obj, btree_obj); recman.close(); } /** * Test to remove objects from the btree. (cdaller) */ public void testRemove() throws IOException { RecordManager recman; BTree tree; if ( DEBUG ) { System.out.println( "TestBTree.testRemove" ); } recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new StringComparator() ); tree.insert("test1", "value1",false); tree.insert("test2","value2",false); assertEquals("value1",(String)tree.find("test1")); assertEquals("value2",(String)tree.find("test2")); tree.remove("test1"); assertEquals(null,(String)tree.find("test1")); assertEquals("value2",(String)tree.find("test2")); tree.remove("test2"); assertEquals(null,(String)tree.find("test2")); int iterations = 1000; for ( int count = 0; count < iterations; count++ ) { tree.insert( "num"+count, new Integer( count ), false ); } assertEquals( iterations, tree.size() ); for ( int count = 0; count < iterations; count++ ) { assertEquals( new Integer( count ), tree.find( "num" + count ) ); } for ( int count = 0; count < iterations; count++ ) { tree.remove( "num" + count ); } assertEquals( 0, tree.size() ); recman.close(); } /** * Test to find differents objects in the btree. (cdaller) */ public void testFind() throws IOException { RecordManager recman; BTree tree; if ( DEBUG ) System.out.println("TestBTree.testFind"); recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new StringComparator() ); tree.insert("test1", "value1",false); tree.insert("test2","value2",false); Object value = tree.find("test1"); assertTrue(value instanceof String); assertEquals("value1",value); tree.insert("","Empty String as key",false); assertEquals("Empty String as key",(String)tree.find("")); assertEquals(null,(String)tree.find("someoneelse")); recman.close(); } /** * Test to insert, retrieve and remove a large amount of data. (cdaller) */ public void testLargeDataAmount() throws IOException { RecordManager recman; BTree tree; if ( DEBUG ) System.out.println("TestBTree.testLargeDataAmount"); recman = RecordManagerFactory.createRecordManager( "test" ); // recman = new jdbm.recman.BaseRecordManager( "test" ); tree = BTree.createInstance( recman, new StringComparator() ); // tree.setSplitPoint( 4 ); int iterations = 10000; // insert data for ( int count = 0; count < iterations; count++ ) { try { assertEquals(null,tree.insert("num"+count,new Integer(count),false)); } catch ( IOException except ) { except.printStackTrace(); throw except; } } // find data for(int count = 0; count < iterations; count++) { assertEquals(new Integer(count), tree.find("num"+count)); } // delete data for(int count = 0; count < iterations; count++) { assertEquals(new Integer(count),tree.remove("num"+count)); } assertEquals(0,tree.size()); recman.close(); } /** * Test access from multiple threads. Assertions only work, when the * run() method is overridden and the exceptions of the threads are * added to the resultset of the TestCase. see run() and * handleException(). */ public void testMultithreadAccess() throws IOException { RecordManager recman; BTree tree; if ( DEBUG ) System.out.println("TestBTree.testMultithreadAccess"); recman = RecordManagerFactory.createRecordManager( "test" ); tree = BTree.createInstance( recman, new StringComparator() ); TestThread[] thread_pool = new TestThread[THREAD_NUMBER]; String name; Map content; // create content for the tree, different content for different threads! for (int thread_count = 0; thread_count < THREAD_NUMBER; thread_count++) { name = "thread"+thread_count; content = new TreeMap(); for(int content_count = 0; content_count < THREAD_CONTENT_SIZE; content_count++) { // guarantee, that keys and values do not overleap, // otherwise one thread removes some keys/values of // other threads! content.put( name+"_"+content_count, new Integer(thread_count*THREAD_CONTENT_SIZE+content_count) ); } thread_pool[thread_count] = new TestThread(name,tree,content); thread_pool[thread_count].start(); } try { Thread.sleep(THREAD_RUNTIME); } catch( InterruptedException ignore ) { ignore.printStackTrace(); } // stop threads: for (int thread_count = 0; thread_count < THREAD_NUMBER; thread_count++) { if ( DEBUG ) System.out.println("Stop threads"); thread_pool[thread_count].setStop(); } // wait until the threads really stop: try { for (int thread_count = 0; thread_count < THREAD_NUMBER; thread_count++) { if ( DEBUG ) System.out.println("Join thread " + thread_count ); thread_pool[thread_count].join(); if ( DEBUG ) System.out.println("Joined thread " + thread_count ); } } catch( InterruptedException ignore ) { ignore.printStackTrace(); } recman.close(); } /** * Helper method to 'simulate' the methods of an entry set of the btree. */ protected static boolean containsKey( Object key, BTree btree ) throws IOException { return ( btree.find( key ) != null ); } /** * Helper method to 'simulate' the methods of an entry set of the btree. */ protected static boolean containsValue( Object value, BTree btree ) throws IOException { // we must synchronize on the BTree while browsing synchronized ( btree ) { TupleBrowser browser = btree.browse(); Tuple tuple = new Tuple(); while(browser.getNext(tuple)) { if(tuple.getValue().equals(value)) return(true); } } // System.out.println("Comparation of '"+value+"' with '"+ tuple.getValue()+"' FAILED"); return(false); } /** * Helper method to 'simulate' the methods of an entry set of the btree. */ protected static boolean contains( Map.Entry entry, BTree btree ) throws IOException { Object tree_obj = btree.find(entry.getKey()); if ( tree_obj == null ) { // can't distuingish, if value is null or not found!!!!!! return ( entry.getValue() == null ); } return ( tree_obj.equals( entry.getValue() ) ); } /** * Runs all tests in this class */ public static void main( String[] args ) { junit.textui.TestRunner.run( new TestSuite( TestBTree.class ) ); } /** * Inner class for testing puroposes only (multithreaded access) */ class TestThread extends Thread { Map _content; BTree _btree; volatile boolean _continue = true; int THREAD_SLEEP_TIME = 50; // in ms String _name; TestThread( String name, BTree btree, Map content ) { _content = content; _btree = btree; _name = name; } public void setStop() { _continue = false; } private void action() throws IOException { Iterator iterator = _content.entrySet().iterator(); Map.Entry entry; if ( DEBUG ) { System.out.println("Thread "+_name+": fill btree."); } while( iterator.hasNext() ) { entry = (Map.Entry) iterator.next(); assertEquals( null, _btree.insert( entry.getKey(), entry.getValue(), false ) ); } // as other threads are filling the btree as well, the size // of the btree is unknown (but must be at least the size of // the content map) assertTrue( _content.size() <= _btree.size() ); iterator = _content.entrySet().iterator(); if ( DEBUG ) { System.out.println( "Thread " + _name + ": iterates btree." ); } while( iterator.hasNext() ) { entry = (Map.Entry) iterator.next(); assertEquals( entry.getValue(), _btree.find( entry.getKey() ) ); assertTrue( contains( entry, _btree ) ); assertTrue( containsKey( entry.getKey(), _btree ) ); assertTrue( containsValue( entry.getValue(), _btree ) ); } iterator = _content.entrySet().iterator(); Object key; if ( DEBUG ) { System.out.println( "Thread " + _name + ": removes his elements from the btree." ); } while( iterator.hasNext() ) { key = ( (Map.Entry) iterator.next() ).getKey(); _btree.remove( key ); assertTrue( ! containsKey( key,_btree ) ); } } public void run() { if(DEBUG) System.out.println("Thread "+_name+": started."); try { while(_continue) { action(); try { Thread.sleep(THREAD_SLEEP_TIME); } catch( InterruptedException except ) { except.printStackTrace(); } } } catch( Throwable t ) { if ( DEBUG ) { System.err.println("Thread "+_name+" threw an exception:"); t.printStackTrace(); } handleThreadException(t); } if(DEBUG) System.out.println("Thread "+_name+": stopped."); } } // end of class TestThread } /** * class for testing puroposes only (store as value in btree) not * implemented as inner class, as this prevents Serialization if * outer class is not Serializable. */ class TestObject implements Serializable { Object _content; private TestObject() { // empty } public TestObject( Object content ) { _content = content; } Object getContent() { return _content; } public boolean equals( Object obj ) { if ( ! ( obj instanceof TestObject ) ) { return false; } return _content.equals( ( (TestObject) obj ).getContent() ); } public String toString() { return( "TestObject {content='" + _content + "'}" ); } } // TestObject libjdbm-java-1.0.orig/src/tests/jdbm/btree/TestInsertPerf.java0000644000175000017500000000400110276576000024321 0ustar twernertwerner package jdbm.btree; import java.io.IOException; import java.util.Properties; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.btree.BTree; import jdbm.helper.LongComparator; /** * Test BTree insert performance. */ public class TestInsertPerf { int _numberOfObjects; public TestInsertPerf( int numberOfObjects ) { _numberOfObjects = numberOfObjects; } public void insert() throws IOException { BTree btree; RecordManager recman; long start, finish; Properties props; props = new Properties(); recman = RecordManagerFactory.createRecordManager( "TestInsertPref-" + System.currentTimeMillis(), props); btree = BTree.createInstance( recman, new LongComparator() ); // Note: One can use specialized serializers for better performance / database size // btree = BTree.createInstance( recman, new LongComparator(), // LongSerializer.INSTANCE, IntegerSerializer.INSTANCE ); start = System.currentTimeMillis(); for (int i = 0; i < _numberOfObjects; i++) { btree.insert( new Long( i ), new Integer( i ), false ); } recman.commit(); finish = System.currentTimeMillis(); System.out.println( "It took " + (finish - start) + " ms to insert " + _numberOfObjects +" objects." ); } public static void main( String[] args ) { if ( args.length != 1 ) { System.out.println( "Usage: TestInsertPerf [numberOfObjects]" ); return; } int numberOfObjects = Integer.parseInt( args[ 0 ] ); TestInsertPerf test = new TestInsertPerf( numberOfObjects ); try { test.insert(); } catch ( IOException except ) { except.printStackTrace(); } } } libjdbm-java-1.0.orig/src/tests/jdbm/helper/0000775000175000017500000000000010276576000020722 5ustar twernertwernerlibjdbm-java-1.0.orig/src/tests/jdbm/helper/Test.java0000644000175000017500000000513110276576000022502 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.helper; import junit.framework.*; /** * Package test suite. * * @author Alex Boisvert * @version $Id: Test.java,v 1.4 2003/11/01 13:31:06 dranatunga Exp $ */ public class Test extends TestCase { public Test(String name) { super(name); } public static junit.framework.Test suite() { TestSuite retval = new TestSuite(); retval.addTest(new TestSuite(TestMRU.class)); retval.addTest(new TestSuite(TestSoftCache.class)); return retval; } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } } libjdbm-java-1.0.orig/src/tests/jdbm/helper/TestCachePolicy.java0000644000175000017500000003054310276576000024613 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id */ package jdbm.helper; import java.util.ArrayList; import junit.framework.TestCase; /** * Abstract class that provides some convenience test cases, * classes and methods for any class that tests an implementation * of {@link CachePolicy}. *

* Concrete subclasses must provide {@link #createInstance(int)}. They may * also need to override {@link #causeEviction(CachePolicy, int)} if the * default strategy will not suffice for the implementation of being tested. * * @author Dilum Ranatunga * @version $Id: TestCachePolicy.java,v 1.1 2003/11/01 13:26:19 dranatunga Exp $ */ public abstract class TestCachePolicy extends TestCase { protected TestCachePolicy(String string) { super(string); } /** * Factory that test methods use to create test instances. The instance * should be capable of storing the specified number of large objects * without an eviction. Large objects are created by {@link #createLargeObject()}. * * @param capacity the number of large objects the instance should be * capable of containing. * @return a non-null cache instance. */ protected abstract CachePolicy createInstance(int capacity); /** * Causes at least one eviction from the specified cache. *

* Note: take care when overriding this with implementations that depend * on adding a temporary listener to the cache. Such a scheme can cause * an infinite loop when testing adding and removing listeners. * * @param cache a cache object. It is generally safe to assume that this * was created using {@link #createInstance(int)}. * @param capacity the capacity used when cache was created. * @throws CacheEvictionException */ protected void causeEviction(final CachePolicy cache, final int capacity) throws CacheEvictionException { for (int i = 0; i < capacity; ++i) { cache.put(new Object(), new Object()); } } /** * Tests {@link CachePolicy#addListener(CachePolicyListener)}, * {@link CachePolicy#removeListener(CachePolicyListener)}. */ public void testAddRemoveListeners() { try { final CountingListener listener1 = new CountingListener("Listener1"); final CountingListener listener2_1 = new CountingListener("Listener2"); final CountingListener listener2_2 = new CountingListener("Listener2"); final int capacity = 2; final CachePolicy cache = createInstance(capacity); { // quick check of assumptions assertTrue("Listeners should be equal.", listener2_1.equals(listener2_2)); assertTrue("Equal listeners' hashcodes should be equal.", listener2_1.hashCode() == listener2_2.hashCode()); } { // bad input test try { cache.addListener(null); fail("cache.addListener(null) should throw IllegalArgumentRxception."); } catch (IllegalArgumentException e) { } } { // null test causeEviction(cache, capacity); assertEquals(0, listener1.count()); assertEquals(0, listener2_1.count()); assertEquals(0, listener2_2.count()); } { // show that add affects cache, listener cache.addListener(listener1); causeEviction(cache, capacity); assertTrue("listener not getting added, " + "not getting eviction event " + " or causeEviction not working)", listener1.count() > 0); } { // show that remove affects cache, listener listener1.reset(); cache.removeListener(listener1); causeEviction(cache, capacity); assertTrue("listener not getting removed", listener1.count() == 0); } { // show that multiple listeners are used listener1.reset(); listener2_1.reset(); listener2_2.reset(); cache.addListener(listener1); cache.addListener(listener2_1); cache.addListener(listener2_2); causeEviction(cache, capacity); assertTrue(listener1.count() > 0); // note XOR: only one of the listeners should have received the event. assertTrue((listener2_1.count() > 0) ^ (listener2_2.count() > 0)); } { // show that multiple adds of equal listeners is undone with single remove cache.removeListener(listener2_1); cache.removeListener(listener2_2); listener2_1.reset(); listener2_2.reset(); causeEviction(cache, capacity); assertTrue((listener2_1.count() == 0) && (listener2_2.count() == 0)); cache.addListener(listener2_1); cache.addListener(listener2_2); causeEviction(cache, capacity); assertTrue((listener2_1.count() > 0) ^ (listener2_2.count() > 0)); listener2_1.reset(); listener2_2.reset(); cache.removeListener(listener2_1); // note: only one is removed. causeEviction(cache, capacity); assertTrue((listener2_1.count() == 0) && (listener2_2.count() == 0)); } } catch (CacheEvictionException cex) { fail("Cache is throwing eviction exceptions even though none of the listeners are."); } } /** * Ensures that the {@link CachePolicy} implementation propagates * {@link CacheEvictionException}s back to the caller. */ public void testEvictionExceptionPropagation() throws CacheEvictionException { final CachePolicyListener quietListener = new CountingListener("quiet"); final CachePolicyListener throwingListener = new ThrowingListener(); final int capacity = 1; final CachePolicy cache = createInstance(capacity); { // null test. cache.addListener(quietListener); cache.removeAll(); try { causeEviction(cache, capacity); } catch (CacheEvictionException cex) { fail("Threw eviction exception when it wasn't supposed to: " + cex); } cache.removeListener(quietListener); } { // propagation test cache.addListener(throwingListener); try { causeEviction(cache, capacity); fail("Did not propagate expected exception."); } catch (CacheEvictionException cex) { } cache.removeListener(throwingListener); } } protected void causeGarbageCollection() { try { ArrayList l = new ArrayList(); for (int i = 0; i < 500; ++i) { l.add(createLargeObject()); } } catch (OutOfMemoryError oome) { } for (int i = 0; i < 10; ++i) { System.gc(); } } protected Object createLargeObject() { int[] a = new int[1024 * 1024]; // 1M of ints. // Fill the array. This is done to prevent any sneaky VMs from // saving space by lazily allocating the full array. for (int i = a.length; --i >= 0;) { a[i] = i; } return a; } /** * Listener used to test whether the event method is being invoked. * Typical usage idiom is of the form: *

     * CachePolicy cache = ...;
     * CountingListener listener = new CountingListener("mylistener");
     * ...
     * listener.reset();
     * cache.addListener(listener);
     * // do stuff with cache
     * assertTrue(listener.count() > 0);
     * 
*/ protected static final class CountingListener implements CachePolicyListener { private String _name; private int _count = 0; /** * Creates a counting listener with the name specified. * @param name the (non-null) name of the listener. */ CountingListener(String name) { _name = new String(name); // this automatically throws NPE if name is null. } /** * Implimentation of callback method that increments count. */ public void cacheObjectEvicted(Object obj) throws CacheEvictionException { _count++; } /** * Reset's this listener's count to zero. */ void reset() { _count = 0; } /** * Gets this listener's current count: the number of times the * callback method's been invoked since creation/reset. * @return */ int count() { return _count; } /** * Equality defined as (same type) AND (names equal). */ public boolean equals(Object obj) { if (!(obj instanceof CountingListener)) { return false; } return _name.equals(((CountingListener) obj)._name); } /** * Defined as hashcode of name; consistent with {@link #equals(Object)}. */ public int hashCode() { return _name.hashCode(); } } /** * Listener used to cause a {@link CacheEvictionException}. * Typical usage idiom is of the form: *
     * CachePolicy cache = ...;
     * ThrowingListener listener = new ThrowingListener();
     * ...
     * // cause cache evictions without exceptions.
     * cache.addListener(listener);
     * try {
     *   // cause a cache eviction.
     *   fail("exception expected");
     * } catch (CacheEvictionException e) { }
     * 
*/ protected static final class ThrowingListener implements CachePolicyListener { protected static final String MESSAGE = "Intentionally thrown for testing purposes."; /** * Always throws a {@link CacheEvictionException} wrapping a * runtime exception with the message {@link #MESSAGE}. */ public void cacheObjectEvicted(Object obj) throws CacheEvictionException { throw new CacheEvictionException(new RuntimeException(MESSAGE)); } } } libjdbm-java-1.0.orig/src/tests/jdbm/helper/TestMRU.java0000644000175000017500000001367010276576000023075 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.helper; import junit.framework.TestSuite; /** * Unit test for {@link MRU}. * * @author Alex Boisvert * @author Dilum Ranatunga * @version $Id: TestMRU.java,v 1.3 2003/11/01 13:27:18 dranatunga Exp $ */ public class TestMRU extends TestCachePolicy { public TestMRU(String name) { super(name); } protected CachePolicy createInstance(int capacity) { return new MRU(capacity); } /** * Test constructor */ public void testConstructor() { try { // should not support 0-size cache MRU m1 = new MRU(0); fail("expected exception"); } catch (Exception e) { } MRU m5 = new MRU(5); } /** * Test eviction */ public void testEvict() throws CacheEvictionException { Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); Object o4 = new Object(); Object o5 = new Object(); MRU m1 = new MRU(3); m1.put("1", o1); m1.put("2", o2); m1.put("3", o3); m1.put("4", o4); assertEquals(null, m1.get("1")); assertEquals(o2, m1.get("2")); assertEquals(o3, m1.get("3")); assertEquals(o4, m1.get("4")); } /** * Test key replacement */ public void testReplace() throws CacheEvictionException { Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); Object o4 = new Object(); MRU m1 = new MRU(3); m1.put("1", o1); m1.put("2", o2); m1.put("3", o3); m1.put("1", o4); assertEquals(o4, m1.get("1")); assertEquals(o2, m1.get("2")); assertEquals(o3, m1.get("3")); } /** * Test multiple touch */ public void testMultiple() throws CacheEvictionException { Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); Object o4 = new Object(); MRU m1 = new MRU(3); m1.put("1", o1); m1.put("2", o2); m1.put("3", o3); m1.put("3", o3); m1.put("3", o3); m1.put("3", o3); assertEquals(o1, m1.get("1")); assertEquals(o2, m1.get("2")); assertEquals(o3, m1.get("3")); m1.put("1", o3); // replace with o3 m1.put("4", o4); // should evict 2 assertEquals(o4, m1.get("4")); assertEquals(o3, m1.get("3")); assertEquals(o3, m1.get("1")); assertEquals(null, m1.get("2")); } public void testEvictionExceptionRecovery() throws CacheEvictionException { final CachePolicy cache = new MRU(1); final Object oldKey = "to-be-evicted"; final Object newKey = "insert-attempt"; { // null test cache.removeAll(); cache.put(oldKey, new Object()); assertNotNull(cache.get(oldKey)); cache.put(newKey, new Object()); assertNull(cache.get(oldKey)); assertNotNull(cache.get(newKey)); } { // stability test. cache.removeAll(); cache.addListener(new ThrowingListener()); cache.put(oldKey, new Object()); assertNotNull(cache.get(oldKey)); try { cache.put(newKey, new Object()); fail("Did not propagate expected exception."); } catch (CacheEvictionException cex) { assertNotNull("old object missing after eviction exception!", cache.get(oldKey)); assertNull("new key -> object mapping added even when eviction exception!", cache.get(newKey)); } } } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestMRU.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/helper/TestSoftCache.java0000644000175000017500000002472110276576000024270 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.helper; import java.lang.ref.SoftReference; import junit.framework.AssertionFailedError; /** * Unit test for {@link SoftCache}. * * @author Dilum Ranatunga * @version $Id: TestSoftCache.java,v 1.1 2003/11/01 13:29:57 dranatunga Exp $ */ public class TestSoftCache extends TestCachePolicy { public TestSoftCache(String name) { super(name); } /** * Tests {@link SoftCache#SoftCache()} , * {@link SoftCache#SoftCache(CachePolicy)}, * {@link SoftCache#SoftCache(float, CachePolicy)}. */ public void testConstructor() { { // test that null parameter fails try { new SoftCache(null); fail("constructor will null should have failed."); } catch (NullPointerException npe) { } try { new SoftCache(null); fail("constructor will null should have failed."); new SoftCache(0.5f, null); } catch (NullPointerException npx) { } } { // test that bad load factor fails. try { new SoftCache(0.0f, new MRU(5)); fail("zero load factor should fail"); } catch (IllegalArgumentException iax) { } } { // test correct instantiations new SoftCache(); new SoftCache(new MRU(5)); new SoftCache(0.1f, new MRU(5)); new SoftCache(10.0f, new MRU(5)); } } /** * Ensures that {@link SoftCache#put(Object, Object)} operations are * delegated to the internal cache. */ public void testPutDelegation() throws CacheEvictionException { final int capacity = 5; final CachePolicy internal = new MRU(capacity); final CachePolicy level2 = new SoftCache(internal); final Object key = new Integer(0); final Object value = "EXPECTED-VALUE"; level2.put(key, value); assertSame("L2.get() did not return expected.", value, level2.get(key)); assertSame("L1.get() did not return expected.", value, internal.get(key)); causeEviction(level2, capacity); assertNull(internal.get(key)); } /** * Shows that a soft cache can recover an evicted object, and that * this recovery is conditioned on soft references not having been * cleared. */ public void testL2Recovery() throws CacheEvictionException { final int capacity = 5; // since soft reference clears are not predictable, we use a indicator indicator final SoftReference indicator = new SoftReference(createLargeObject()); final CachePolicy internal = new MRU(capacity); final CachePolicy level2 = new SoftCache(internal); for (int attempts = 100; attempts-- > 0;) { // keep looping until we get to complete the whole test, or until. // we've tried the number of attempts we're willing to make. boolean heuristicRedFlag = false; for (int i = 0; i <= capacity; ++i) { // note <= level2.put("" + i, createLargeObject()); } // look in least recently used: '0' assertNull("'0' should have been evicted from internal", internal.get("0")); assertNotNull("'0' should still be accessible through L2", level2.get("0")); // this will cause '0' to get readded to internal: // this construct restarts the test if indicator if (null == indicator.get()) { heuristicRedFlag = true; } causeGarbageCollection(); if (null != indicator.get()) { heuristicRedFlag = true; } try { // since '0' was readded, least recently used is '1' assertNull("'1' should have been evicted from internal", internal.get("1")); assertNull("Soft references should have cleared during gc", level2.get("1")); // getting here means test successful. no need to make // any further attempts. return; } catch (AssertionFailedError afe) { // The test failed. But if we have a heuristic red flag, // we should return. Otherwise, fail the test. if (!heuristicRedFlag) { throw afe; } } } // getting here means we were unable to test the condition. fail("Could not perform soft cache test to completion."); } /** * Tests {@link SoftCache#removeAll()} */ public void testRemoveAll() throws CacheEvictionException { final int capacity = 5; final CachePolicy internal = new MRU(capacity); final CachePolicy level2 = new SoftCache(internal); // add a bunch. for (int i = 0; i < (capacity + 2); ++i) { level2.put("" + i, createLargeObject()); } // show that some are still in internal int count = 0; for (int i = 0; i < (capacity + 2); ++i) { if (null != internal.get("" + i)) { count++; } } assertTrue(count > 0); // show that all exist in level2. for (int i = 0; i < (capacity + 2); ++i) { assertNotNull(level2.get("" + i)); } // show that none exist after removeall. level2.removeAll(); for (int i = 0; i < (capacity + 2); ++i) { assertNull(internal.get("" + i)); assertNull(level2.get("" + i)); } } /** * Shows that {@link SoftCache#remove(Object)} clears objects that * are only in L2. */ public void testRemoveClearsL2Objects() throws CacheEvictionException { final int capacity = 5; final CachePolicy internal = new MRU(capacity); final CachePolicy level2 = new SoftCache(internal); { // control test: show recovery for (int i = 0; i < (capacity + 2); ++i) { level2.put("" + i, createLargeObject()); } // "0", "1" evicted. assertNull(internal.get("0")); assertNull(internal.get("1")); assertNotNull(internal.get("2")); assertNotNull(level2.get("0")); assertNotNull(level2.get("1")); assertNotNull(level2.get("2")); } level2.removeAll(); // this has already been tested { // test remove: for (int i = 0; i < (capacity + 2); ++i) { level2.put("" + i, createLargeObject()); } // "0", "1" evicted, as before. // Now, we remove "1" -- L2 only object, and // "2" -- internal and L2 object level2.remove("1"); level2.remove("2"); assertNull(internal.get("0")); assertNull(internal.get("1")); assertNull(internal.get("2")); assertNotNull(level2.get("0")); assertNull(level2.get("1")); assertNull(level2.get("2")); } } public void testExceptionDuringReinstate() throws CacheEvictionException { final int capacity = 5; final CachePolicy internal = new MRU(capacity); final CachePolicy level2 = new SoftCache(internal); final CachePolicyListener listener = new ThrowingListener(); // Fill internal cache, and overflow by three: "0", "1", "2" evicted from internal for (int i = 0; i < (capacity + 3); ++i) { level2.put("" + i, new Object()); } { // Null test. Cause "0" to get reinserted. assertNull(internal.get("0")); assertNotNull(level2.get("0")); assertNotNull(internal.get("0")); } { // Test handling of exception during reinsertion level2.addListener(listener); assertNull(internal.get("1")); assertNull(level2.get("1")); // this would have caused a reinsertion assertNull(internal.get("1")); } { // Test stability: when listener is removed, things are back to normal level2.removeListener(listener); assertNull(internal.get("2")); assertNotNull(level2.get("2")); assertNotNull(internal.get("2")); } } protected CachePolicy createInstance(final int capacity) { return new SoftCache(new MRU(capacity)); } } libjdbm-java-1.0.orig/src/tests/jdbm/htree/0000775000175000017500000000000010276576000020552 5ustar twernertwernerlibjdbm-java-1.0.orig/src/tests/jdbm/htree/Test.java0000644000175000017500000000540310276576000022334 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.htree; import junit.framework.*; /** * "jdbm.hash.*" package test suite * * @author Alex Boisvert * @version $Id: Test.java,v 1.3 2003/07/31 15:21:57 boisvert Exp $ */ public class Test extends TestCase { public Test(String name) { super(name); } public static junit.framework.Test suite() { TestSuite retval = new TestSuite(); retval.addTest(new TestSuite(TestHashBucket.class)); retval.addTest(new TestSuite(TestHashDirectory.class)); retval.addTest(new TestSuite(TestRollback.class)); retval.addTest(new TestSuite(TestHTree.class)); return retval; } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } } libjdbm-java-1.0.orig/src/tests/jdbm/htree/TestHashBucket.java0000644000175000017500000000746710276576000024312 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.htree; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.recman.TestRecordFile; import java.io.IOException; import java.util.Properties; import junit.framework.*; /** * This class contains all Unit tests for {@link HashBucket}. * * @author Alex Boisvert * @version $Id: TestHashBucket.java,v 1.1 2002/05/31 06:50:14 boisvert Exp $ */ public class TestHashBucket extends TestCase { public TestHashBucket(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Basic tests */ public void testBasics() throws IOException { Properties props = new Properties(); RecordManager recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName, props ); HashBucket bucket = new HashBucket(0); // add bucket.addElement("key", "value"); String s = (String)bucket.getValue("key"); assertEquals("value", s); // replace bucket.addElement("key", "value2"); s = (String)bucket.getValue("key"); assertEquals("value2", s); // add bucket.addElement("key2", "value3"); s = (String)bucket.getValue("key2"); assertEquals("value3", s); // remove bucket.removeElement("key2"); s = (String)bucket.getValue("key2"); assertEquals(null, s); bucket.removeElement("key"); s = (String)bucket.getValue("key"); assertEquals(null, s); recman.close(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestHashBucket.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/htree/TestHashDirectory.java0000644000175000017500000001450110276576000025024 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.htree; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.recman.TestRecordFile; import jdbm.helper.FastIterator; import junit.framework.*; import java.io.IOException; import java.util.Hashtable; import java.util.Properties; /** * This class contains all Unit tests for {@link HashDirectory}. * * @author Alex Boisvert * @version $Id: TestHashDirectory.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ */ public class TestHashDirectory extends TestCase { public TestHashDirectory(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Basic tests */ public void testBasics() throws IOException { System.out.println("testBasics"); Properties props = new Properties(); RecordManager recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName, props ); HashDirectory dir = new HashDirectory((byte)0); long recid = recman.insert(dir); dir.setPersistenceContext(recman, recid); dir.put("key", "value"); String s = (String)dir.get("key"); assertEquals("value", s); recman.close(); } /** * Mixed tests */ public void testMixed() throws IOException { System.out.println("testMixed"); Properties props = new Properties(); RecordManager recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName, props ); HashDirectory dir = new HashDirectory((byte)0); long recid = recman.insert(dir); dir.setPersistenceContext(recman, recid); Hashtable hash = new Hashtable(); // use to compare results int max = 30; // must be even // insert & check values for (int i=0; iAlex Boisvert * @version $Id: TestHTree.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ */ public class TestHTree extends TestCase { public TestHTree(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Basic tests */ public void testIterator() throws IOException { Properties props = new Properties(); RecordManager recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName, props ); HTree testTree = getHtree(recman, "htree"); int total = 10; for ( int i = 0; i < total; i++ ) { testTree.put( Long.valueOf("" + i), Long.valueOf("" + i) ); } recman.commit(); FastIterator fi = testTree.values(); Object item; int count = 0; while( (item = fi.next()) != null ) { count++; } assertEquals( count, total ); recman.close(); } private static HTree getHtree( RecordManager recman, String name ) throws IOException { long recId = recman.getNamedObject("htree"); HTree testTree; if ( recId != 0 ) { testTree = HTree.load( recman, recId ); } else { testTree = HTree.createInstance( recman ); recman.setNamedObject( "htree", testTree.getRecid() ); } return testTree; } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestHTree.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/htree/TestRollback.java0000644000175000017500000001134410276576000024007 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * */ package jdbm.htree; import jdbm.RecordManager; import jdbm.recman.BaseRecordManager; import jdbm.recman.TestRecordFile; import junit.framework.*; /** * Test cases for HTree rollback */ public class TestRollback extends TestCase { public TestRollback( String name ) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test case courtesy of Derek Dick (mailto:ddick@users.sourceforge.net) */ public void testRollback1() throws Exception { RecordManager recman; long root; // Note: We start out with an empty file recman = new BaseRecordManager( TestRecordFile.testFileName ); root = recman.getNamedObject( "xyz" ); HTree tree = null; if ( root == 0 ) { // create a new one tree = HTree.createInstance( recman ); root = tree.getRecid(); recman.setNamedObject( "xyz", root ); recman.commit(); } else { tree = HTree.load( recman, root ); } tree.put( "Foo", "Bar" ); tree.put( "Fo", "Fum" ); recman.commit(); tree.put( "Hello", "World" ); recman.rollback(); tree = HTree.load( recman, root ); assertTrue( tree.get( "Foo" ).equals( "Bar" ) ); assertTrue( tree.get( "Fo" ).equals( "Fum" ) ); assertTrue( tree.get( "Hello" ) == null ); } /** * Test case courtesy of Derek Dick (mailto:ddick@users.sourceforge.net) */ public void testRollback2() throws Exception { RecordManager recman; long root; // Note: We start out with an empty file recman = new BaseRecordManager( TestRecordFile.testFileName ); root = recman.getNamedObject( "xyz" ); HTree tree = null; if ( root == 0 ) { // create a new one tree = HTree.createInstance( recman ); root = tree.getRecid(); recman.setNamedObject( "xyz", root ); recman.commit(); } else { tree = HTree.load( recman, root ); } tree.put( "hello", "world" ); tree.put( "goodnight", "gracie" ); recman.commit(); tree.put( "derek", "dick" ); recman.rollback(); assertTrue( tree.get( "derek" ) == null ); assertTrue( tree.get( "goodnight" ).equals( "gracie" ) ); assertTrue( tree.get( "hello" ).equals( "world" ) ); } /** * Runs all tests in this class */ public static void main( String[] args ) { junit.textui.TestRunner.run( new TestSuite( TestRollback.class ) ); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/0000775000175000017500000000000010276576000020710 5ustar twernertwernerlibjdbm-java-1.0.orig/src/tests/jdbm/recman/Test.java0000644000175000017500000000461310276576000022474 0ustar twernertwerner/* * $Id: Test.java,v 1.1 2000/05/06 00:00:53 boisvert Exp $ * * Package test suite * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; public class Test extends TestCase { public Test(String name) { super(name); } public static junit.framework.Test suite() { TestSuite retval = new TestSuite(); retval.addTest(new TestSuite(TestBlockIo.class)); retval.addTest(new TestSuite(TestLocation.class)); retval.addTest(new TestSuite(TestFileHeader.class)); retval.addTest(new TestSuite(TestPhysicalRowId.class)); retval.addTest(new TestSuite(TestFreePhysicalRowId.class)); retval.addTest(new TestSuite(TestFreePhysicalRowIdPage.class)); retval.addTest(new TestSuite(TestFreePhysicalRowIdPageManager.class)); retval.addTest(new TestSuite(TestFreeLogicalRowIdPage.class)); retval.addTest(new TestSuite(TestFreeLogicalRowIdPageManager.class)); retval.addTest(new TestSuite(TestRecordHeader.class)); retval.addTest(new TestSuite(TestTransactionManager.class)); retval.addTest(new TestSuite(TestRecordFile.class)); retval.addTest(new TestSuite(TestPageHeader.class)); retval.addTest(new TestSuite(TestPageCursor.class)); retval.addTest(new TestSuite(TestPageManager.class)); retval.addTest(new TestSuite(TestDataPage.class)); retval.addTest(new TestSuite(TestPhysicalRowIdManager.class)); retval.addTest(new TestSuite(TestLogicalRowIdManager.class)); retval.addTest(new TestSuite(TestRecordManager.class)); return retval; } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestBlockIo.java0000644000175000017500000000500710276576000023735 0ustar twernertwerner/* * $Id: TestBlockIo.java,v 1.1 2000/05/06 00:00:53 boisvert Exp $ * * Unit tests for BlockIo class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; import java.io.*; /** * This class contains all Unit tests for {@link BlockIo}. */ public class TestBlockIo extends TestCase { private static final short SHORT_VALUE = 0x1234; private static final int INT_VALUE = 0xe7b3c8a1; private static final long LONG_VALUE = 0xfdebca9876543210L; public TestBlockIo(String name) { super(name); } /** * Test writing */ public void testWrite() throws Exception { byte[] data = new byte[100]; BlockIo test = new BlockIo(0, data); test.writeShort(0, SHORT_VALUE); test.writeLong(2, LONG_VALUE); test.writeInt(10, INT_VALUE); DataInputStream is = new DataInputStream(new ByteArrayInputStream(data)); assertEquals("short", SHORT_VALUE, is.readShort()); assertEquals("long", LONG_VALUE, is.readLong()); assertEquals("int", INT_VALUE, is.readInt()); } /** * Test reading */ public void testRead() throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream(100); DataOutputStream os = new DataOutputStream(bos); os.writeShort(SHORT_VALUE); os.writeLong(LONG_VALUE); os.writeInt(INT_VALUE); byte[] data = bos.toByteArray(); BlockIo test = new BlockIo(0, data); assertEquals("short", SHORT_VALUE, test.readShort(0)); assertEquals("long", LONG_VALUE, test.readLong(2)); assertEquals("int", INT_VALUE, test.readInt(10)); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestBlockIo.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestDataPage.java0000644000175000017500000000421410276576000024060 0ustar twernertwerner/* * $Id: TestDataPage.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for DataPage class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.TestCase; import junit.framework.TestSuite; /** * This class contains all Unit tests for {@link DataPage}. */ public class TestDataPage extends TestCase { public TestDataPage(String name) { super(name); } /** * Test basics - read and write at an offset */ public void testReadWrite() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); test.writeShort(0, (short) (Magic.BLOCK + Magic.USED_PAGE)); DataPage page = new DataPage(test); page.setFirst((short) 1000); assertEquals("first", 1000, page.getFirst()); } /** * Test factory method. */ public void testFactory() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); test.writeShort(0, (short) (Magic.BLOCK + Magic.USED_PAGE)); DataPage page = DataPage.getDataPageView(test); page.setFirst((short) 1000); assertEquals("first", 1000, page.getFirst()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestDataPage.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestFileHeader.java0000644000175000017500000000437010276576000024405 0ustar twernertwerner/* * $Id: TestFileHeader.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for FileHeader class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link FileHeader}. */ public class TestFileHeader extends TestCase { public TestFileHeader(String name) { super(name); } /** * Test set, write, read */ public void testSetWriteRead() throws Exception { BlockIo b = new BlockIo(0, new byte[1000]); FileHeader f = new FileHeader(b, true); for (int i = 0; i < Magic.NLISTS; i++) { f.setFirstOf(i, 100 * i); f.setLastOf(i, 200 * i); } f = new FileHeader(b, false); for (int i = 0; i < Magic.NLISTS; i++) { assertEquals("first " + i, i * 100, f.getFirstOf(i)); assertEquals("last " + i, i * 200, f.getLastOf(i)); } } /** * Test root rowids */ public void testRootRowids() throws Exception { BlockIo b = new BlockIo(0, new byte[RecordFile.BLOCK_SIZE]); FileHeader f = new FileHeader(b, true); for (int i = 0; i < FileHeader.NROOTS; i++) { f.setRoot(i, 100 * i); } f = new FileHeader(b, false); for (int i = 0; i < FileHeader.NROOTS; i++) { assertEquals("root " + i, i * 100, f.getRoot(i)); } } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestFileHeader.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestFreeLogicalRowIdPage.java0000644000175000017500000000573110276576000026335 0ustar twernertwerner/* * $Id: TestFreeLogicalRowIdPage.java,v 1.3 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for FreeLogicalRowIdPage class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.TestCase; import junit.framework.TestSuite; /** * This class contains all Unit tests for {@link FreeLogicalRowIdPage}. */ public class TestFreeLogicalRowIdPage extends TestCase { public TestFreeLogicalRowIdPage(String name) { super(name); } /** * Test constructor - create a page */ public void testCtor() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); new PageHeader(test, Magic.FREELOGIDS_PAGE); FreeLogicalRowIdPage page = new FreeLogicalRowIdPage(test); } /** * Test basics */ public void testBasics() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); new PageHeader(test, Magic.FREELOGIDS_PAGE); FreeLogicalRowIdPage page = new FreeLogicalRowIdPage(test); // we have a completely empty page. assertEquals("zero count", 0, page.getCount()); // three allocs PhysicalRowId id = page.alloc(0); id = page.alloc(1); id = page.alloc(2); assertEquals("three count", 3, page.getCount()); // setup last id (2) id.setBlock(1); id.setOffset((short) 2); // two frees page.free(0); page.free(1); assertEquals("one left count", 1, page.getCount()); assertTrue("isfree 0", page.isFree(0)); assertTrue("isfree 1", page.isFree(1)); assertTrue("isalloc 2", page.isAllocated(2)); // now, create a new page over the data and check whether // it's all the same. page = new FreeLogicalRowIdPage(test); assertEquals("2: one left count", 1, page.getCount()); assertTrue("2: isfree 0", page.isFree(0)); assertTrue("2: isfree 1", page.isFree(1)); assertTrue("2: isalloc 2", page.isAllocated(2)); id = page.get(2); assertEquals("block", 1, id.getBlock()); assertEquals("offset", 2, id.getOffset()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestFreeLogicalRowIdPage.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestFreeLogicalRowIdPageManager.java0000644000175000017500000000447310276576000027632 0ustar twernertwerner/* * $Id: TestFreeLogicalRowIdPageManager.java,v 1.4 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for FreeLogicalRowIdPageManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link FreeLogicalRowIdPageManager}. */ public class TestFreeLogicalRowIdPageManager extends TestCase { public TestFreeLogicalRowIdPageManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); FreeLogicalRowIdPageManager freeMgr = new FreeLogicalRowIdPageManager(f, pm); pm.close(); f.close(); } /** * Test basics */ public void testBasics() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); FreeLogicalRowIdPageManager freeMgr = new FreeLogicalRowIdPageManager(f, pm); // allocate a rowid - should fail on an empty file Location loc = freeMgr.get(); assertTrue("loc is not null?", loc == null); pm.close(); f.close(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestFreeLogicalRowIdPageManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestFreePhysicalRowId.java0000644000175000017500000000403010276576000025731 0ustar twernertwerner/* * $Id: TestFreePhysicalRowId.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for FreePhysicalRowId class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.TestCase; import junit.framework.TestSuite; /** * This class contains all Unit tests for {@link FreePhysicalRowId}. */ public class TestFreePhysicalRowId extends TestCase { private static final short SHORT_VALUE = 0x1234; private static final long LONG_VALUE = 0xfdebca9876543210L; public TestFreePhysicalRowId(String name) { super(name); } /** * Test basics - read and write at an offset */ public void testReadWrite() throws Exception { byte[] data = new byte[100]; BlockIo test = new BlockIo(0, data); FreePhysicalRowId rowid = new FreePhysicalRowId(test, (short) 6); rowid.setBlock(1000); rowid.setOffset((short) 2345); rowid.setSize(0xabcdef); assertEquals("block", 1000, rowid.getBlock()); assertEquals("offset", 2345, rowid.getOffset()); assertEquals("size", 0xabcdef, rowid.getSize()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestFreePhysicalRowId.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestFreePhysicalRowIdPage.java0000644000175000017500000000604410276576000026535 0ustar twernertwerner/* * $Id: TestFreePhysicalRowIdPage.java,v 1.3 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for FreePhysicalRowIdPage class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.TestCase; import junit.framework.TestSuite; /** * This class contains all Unit tests for {@link FreePhysicalRowIdPage}. */ public class TestFreePhysicalRowIdPage extends TestCase { public TestFreePhysicalRowIdPage(String name) { super(name); } /** * Test constructor - create a page */ public void testCtor() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); new PageHeader(test, Magic.FREEPHYSIDS_PAGE); FreePhysicalRowIdPage page = new FreePhysicalRowIdPage(test); } /** * Test basics */ public void testBasics() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); new PageHeader(test, Magic.FREEPHYSIDS_PAGE); FreePhysicalRowIdPage page = new FreePhysicalRowIdPage(test); // we have a completely empty page. assertEquals("zero count", 0, page.getCount()); // three allocs FreePhysicalRowId id = page.alloc(0); id = page.alloc(1); id = page.alloc(2); assertEquals("three count", 3, page.getCount()); // setup last id (2) id.setBlock(1); id.setOffset((short) 2); id.setSize(3); // two frees page.free(0); page.free(1); assertEquals("one left count", 1, page.getCount()); assertTrue("isfree 0", page.isFree(0)); assertTrue("isfree 1", page.isFree(1)); assertTrue("isalloc 2", page.isAllocated(2)); // now, create a new page over the data and check whether // it's all the same. page = new FreePhysicalRowIdPage(test); assertEquals("2: one left count", 1, page.getCount()); assertTrue("2: isfree 0", page.isFree(0)); assertTrue("2: isfree 1", page.isFree(1)); assertTrue("2: isalloc 2", page.isAllocated(2)); id = page.get(2); assertEquals("block", 1, id.getBlock()); assertEquals("offset", 2, id.getOffset()); assertEquals("size", 3, id.getSize()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestFreePhysicalRowIdPage.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestFreePhysicalRowIdPageManager.java0000644000175000017500000000452010276576000030025 0ustar twernertwerner/* * $Id: TestFreePhysicalRowIdPageManager.java,v 1.4 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for FreePhysicalRowIdPageManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link FreePhysicalRowIdPageManager}. */ public class TestFreePhysicalRowIdPageManager extends TestCase { public TestFreePhysicalRowIdPageManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); FreePhysicalRowIdPageManager freeMgr = new FreePhysicalRowIdPageManager(f, pm); pm.close(); f.close(); } /** * Test basics */ public void testBasics() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); FreePhysicalRowIdPageManager freeMgr = new FreePhysicalRowIdPageManager(f, pm); // allocate 10,000 bytes - should fail on an empty file. Location loc = freeMgr.get(10000); assertTrue("loc is not null?", loc == null); pm.close(); f.close(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestFreePhysicalRowIdPageManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestLocation.java0000644000175000017500000000347410276576000024171 0ustar twernertwerner/* * $Id: TestLocation.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for Location class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link Location}. */ public class TestLocation extends TestCase { public TestLocation(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Basic tests */ public void testBasics() { Location loc = new Location(10, (short) 20); long longloc = loc.toLong(); Location loc2 = new Location(longloc); assertEquals("longloc", longloc, loc2.toLong()); assertEquals("block2", 10, loc2.getBlock()); assertEquals("offset2", 20, loc2.getOffset()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestLocation.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestLogicalRowIdManager.java0000644000175000017500000000474310276576000026233 0ustar twernertwerner/* * $Id: TestLogicalRowIdManager.java,v 1.3 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for LogicalRowIdManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link LogicalRowIdManager}. */ public class TestLogicalRowIdManager extends TestCase { public TestLogicalRowIdManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); LogicalRowIdManager logMgr = new LogicalRowIdManager(f, pm); f.forceClose(); } /** * Test basics */ public void testBasics() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); LogicalRowIdManager logMgr = new LogicalRowIdManager(f, pm); Location physid = new Location(20, (short) 234); Location logid = logMgr.insert(physid); assertEquals("check one", physid, logMgr.fetch(logid)); physid = new Location(10, (short) 567); logMgr.update(logid, physid); assertEquals("check two", physid, logMgr.fetch(logid)); logMgr.delete(logid); f.forceClose(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestLogicalRowIdManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestPageCursor.java0000644000175000017500000000507010276576000024465 0ustar twernertwerner/* * $Id: TestPageCursor.java,v 1.3 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for PageCursor class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link PageCursor}. */ public class TestPageCursor extends TestCase { public TestPageCursor(String name) { super(name); } public void setUp() { System.out.println("TestPageCursor.setUp"); TestRecordFile.deleteTestFile(); } public void tearDown() { System.out.println("TestPageCursor.tearDown"); TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { System.out.println("TestPageCursor.testCtor"); RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); PageCursor curs = new PageCursor(pm, 0); f.forceClose(); } /** * Test basics */ public void testBasics() throws Exception { System.out.println("TestPageCursor.testBasics"); RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); // add a bunch of pages long[] recids = new long[10]; for (int i = 0; i < 10; i++) { recids[i] = pm.allocate(Magic.USED_PAGE); } PageCursor curs = new PageCursor(pm, Magic.USED_PAGE); for (int i = 0; i < 10; i++) { assertEquals("record " + i, recids[i], curs.next()); } f.forceClose(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestPageCursor.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestPageHeader.java0000644000175000017500000000331210276576000024375 0ustar twernertwerner/* * $Id: TestPageHeader.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for PageHeader class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link PageHeader}. */ public class TestPageHeader extends TestCase { public TestPageHeader(String name) { super(name); } /** * Test set, write, read */ public void testSetWriteRead() throws Exception { BlockIo data = new BlockIo(0, new byte[RecordFile.BLOCK_SIZE]); PageHeader p = new PageHeader(data, Magic.FREE_PAGE); p.setNext(10); p.setPrev(33); p = new PageHeader(data); assertEquals("next", 10, p.getNext()); assertEquals("prev", 33, p.getPrev()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestPageHeader.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestPageManager.java0000644000175000017500000000513610276576000024565 0ustar twernertwerner/* * $Id: TestPageManager.java,v 1.3 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for PageManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link PageManager}. */ public class TestPageManager extends TestCase { public TestPageManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); f.forceClose(); } /** * Test allocations on a single list. */ public void testAllocSingleList() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); for (int i = 0; i < 100; i++) { assertEquals("allocate ", (long) i + 1, pm.allocate(Magic.USED_PAGE)); } pm.close(); f.close(); f = new RecordFile(TestRecordFile.testFileName); pm = new PageManager(f); PageCursor curs = new PageCursor(pm, Magic.USED_PAGE); long i = 1; while (true) { long cur = curs.next(); if (cur == 0) break; assertEquals("next", i++, cur); if (i > 120) fail("list structure not ok"); } assertEquals("total", 101, i); pm.close(); f.close(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestPageManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestPerformance.java0000644000175000017500000001757010276576000024664 0ustar twernertwerner/* * $Id: TestPerformance.java,v 1.4 2003/09/21 15:49:02 boisvert Exp $ * * Package performance test * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.RecordManagerOptions; import junit.framework.*; import java.util.Properties; import java.util.Random; /** * This class contains performance tests for this package. */ public class TestPerformance extends TestCase { public TestPerformance(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { //TestRecordFile.deleteTestFile(); } // test parameter: maximum record size final int MAXSIZE = 500; // is this a reasonable size for real-world apps? // test parameter: number of records for fetch/update tests final int RECORDS = 10000; Random rnd = new Random(42); /** * Test insert performance */ public void testInserts() throws Exception { RecordManager recman; recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); int inserts = 0; long start = System.currentTimeMillis(); try { long stop = 0; while (true) { recman.insert(TestUtil.makeRecord(rnd.nextInt(MAXSIZE), (byte) rnd.nextInt())); inserts++; if ((inserts % 25) == 0) { stop = System.currentTimeMillis(); if (stop - start >= 60000) break; } } recman.close(); System.out.println("Inserts: " + inserts + " in " + (stop - start) + " millisecs"); } catch (Throwable e) { fail("unexpected exception after " + inserts + " inserts, " + (System.currentTimeMillis() - start) + "ms: " + e); } } /** * Create a database, return array of rowids. */ private long[] makeRows() throws Exception { RecordManager recman; Properties options; options = new Properties(); options.setProperty( RecordManagerOptions.DISABLE_TRANSACTIONS, "true" ); recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName, options ); long[] retval = new long[RECORDS]; System.out.print("Creating test database"); long start = System.currentTimeMillis(); try { for (int i = 0; i < RECORDS; i++) { retval[i] = recman.insert(TestUtil .makeRecord(rnd.nextInt(MAXSIZE), (byte) rnd.nextInt())); if ((i % 100) == 0) System.out.print("."); } recman.close(); } catch (Throwable e) { e.printStackTrace(); fail("unexpected exception during db creation: " + e); } System.out.println("done (" + RECORDS + " inserts in " + (System.currentTimeMillis() - start) + "ms)."); return retval; } /** * Test fetches */ public void testFetches() throws Exception { RecordManager recman; long[] rowids = makeRows(); recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); int fetches = 0; long start = System.currentTimeMillis(); try { long stop = 0; while (true) { recman.fetch( rowids[ rnd.nextInt( RECORDS ) ] ); fetches++; if ((fetches % 25) == 0) { stop = System.currentTimeMillis(); if (stop - start >= 60000) break; } } recman.close(); System.out.println("Fetches: " + fetches + " in " + (stop - start) + " millisecs"); } catch (Throwable e) { fail("unexpected exception after " + fetches + " fetches, " + (System.currentTimeMillis() - start) + "ms: " + e); } } /** * Test updates. */ public void testUpdates() throws Exception { RecordManager recman; long[] rowids = makeRows(); recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); int updates = 0; long start = System.currentTimeMillis(); try { long stop = 0; while (true) { recman.update(rowids[rnd.nextInt(RECORDS)], TestUtil.makeRecord(rnd.nextInt(MAXSIZE), (byte) rnd.nextInt())); updates++; if ((updates % 25) == 0) { stop = System.currentTimeMillis(); if (stop - start >= 60000) break; } } recman.close(); System.out.println("Updates: " + updates + " in " + (stop - start) + " millisecs"); } catch (Throwable e) { fail("unexpected exception after " + updates + " updates, " + (System.currentTimeMillis() - start) + "ms: " + e); } } /** * Test deletes. */ public void testDeletes() throws Exception { RecordManager recman; long[] rowids = makeRows(); recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); int deletes = 0; long start = System.currentTimeMillis(); try { long stop = 0; // This can be done better... for (int i = 0; i < RECORDS; i++) { recman.delete(rowids[i]); deletes++; if ((deletes % 25) == 0) { stop = System.currentTimeMillis(); if (stop - start >= 60000) break; } } recman.close(); System.out.println("Deletes: " + deletes + " in " + (stop - start) + " millisecs"); } catch (Throwable e) { e.printStackTrace(); fail("unexpected exception after " + deletes + " deletes, " + (System.currentTimeMillis() - start) + "ms: " + e); } } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestPerformance.class)); // if you just want one test: // TestSuite suite = new TestSuite(); // suite.addTest(new TestPerformance("testDeletes")); // junit.textui.TestRunner.run(suite); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestPhysicalRowId.java0000644000175000017500000000350610276576000025136 0ustar twernertwerner/* * $Id: TestPhysicalRowId.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for PhysicalRowId class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.TestCase; import junit.framework.TestSuite; /** * This class contains all Unit tests for {@link PhysicalRowId}. */ public class TestPhysicalRowId extends TestCase { public TestPhysicalRowId(String name) { super(name); } /** * Test basics - read and write at an offset */ public void testReadWrite() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); PhysicalRowId rowid = new PhysicalRowId(test, (short) 6); rowid.setBlock(1000); rowid.setOffset((short) 2345); assertEquals("block", 1000, rowid.getBlock()); assertEquals("offset", 2345, rowid.getOffset()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestPhysicalRowId.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestPhysicalRowIdManager.java0000644000175000017500000000663510276576000026437 0ustar twernertwerner/* * $Id: TestPhysicalRowIdManager.java,v 1.5 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for PhysicalRowIdManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; /** * This class contains all Unit tests for {@link PhysicalRowIdManager}. */ public class TestPhysicalRowIdManager extends TestCase { public TestPhysicalRowIdManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); PhysicalRowIdManager physMgr = new PhysicalRowIdManager(f, pm); f.forceClose(); } /** * Test basics */ public void testBasics() throws Exception { RecordFile f = new RecordFile(TestRecordFile.testFileName); PageManager pm = new PageManager(f); PhysicalRowIdManager physMgr = new PhysicalRowIdManager(f, pm); // insert a 10,000 byte record. byte[] data = TestUtil.makeRecord(10000, (byte) 1); Location loc = physMgr.insert( data, 0, data.length ); assertTrue("check data1", TestUtil.checkRecord(physMgr.fetch(loc), 10000, (byte) 1)); // update it as a 20,000 byte record. data = TestUtil.makeRecord(20000, (byte) 2); Location loc2 = physMgr.update(loc, data, 0, data.length ); assertTrue("check data2", TestUtil.checkRecord(physMgr.fetch(loc2), 20000, (byte) 2)); // insert a third record. This'll effectively block the first one // from growing data = TestUtil.makeRecord(20, (byte) 3); Location loc3 = physMgr.insert(data, 0, data.length ); assertTrue("check data3", TestUtil.checkRecord(physMgr.fetch(loc3), 20, (byte) 3)); // now, grow the first record again data = TestUtil.makeRecord(30000, (byte) 4); loc2 = physMgr.update(loc2, data, 0, data.length ); assertTrue("check data4", TestUtil.checkRecord(physMgr.fetch(loc2), 30000, (byte) 4)); // delete the record physMgr.delete(loc2); f.forceClose(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestPhysicalRowIdManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestRecordFile.java0000644000175000017500000001137710276576000024440 0ustar twernertwerner/* * $Id: TestRecordFile.java,v 1.4 2001/11/10 18:36:50 boisvert Exp $ * * Unit tests for RecordFile class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; import java.io.File; import java.io.IOException; /** * This class contains all Unit tests for {@link RecordFile}. */ public class TestRecordFile extends TestCase { public final static String testFileName = "test"; public TestRecordFile( String name ) { super( name ); } public static void deleteFile( String filename ) { File file = new File( filename ); if ( file.exists() ) { try { file.delete(); } catch ( Exception except ) { except.printStackTrace(); } if ( file.exists() ) { System.out.println( "WARNING: Cannot delete file: " + file ); } } } public static void deleteTestFile() { System.gc(); deleteFile(testFileName); deleteFile(testFileName + RecordFile.extension); deleteFile(testFileName + TransactionManager.extension); } public void setUp() { deleteTestFile(); } public void tearDown() { deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordFile file = new RecordFile( testFileName ); file.close(); } /** * Test addition of record 0 */ public void testAddZero() throws Exception { RecordFile file = new RecordFile( testFileName ); byte[] data = file.get( 0 ).getData(); data[ 14 ] = (byte) 'b'; file.release( 0, true ); file.close(); file = new RecordFile( testFileName ); data = file.get( 0 ).getData(); assertEquals( (byte) 'b', data[ 14 ] ); file.release( 0, false ); file.close(); } /** * Test addition of a number of records, with holes. */ public void testWithHoles() throws Exception { RecordFile file = new RecordFile( testFileName ); // Write recid 0, byte 0 with 'b' byte[] data = file.get( 0 ).getData(); data[ 0 ] = (byte) 'b'; file.release( 0, true ); // Write recid 10, byte 10 with 'c' data = file.get( 10 ).getData(); data[ 10 ] = (byte) 'c'; file.release( 10, true ); // Write recid 5, byte 5 with 'e' but don't mark as dirty data = file.get( 5 ).getData(); data[ 5 ] = (byte) 'e'; file.release( 5, false ); file.close(); file = new RecordFile( testFileName ); data = file.get( 0 ).getData(); assertEquals( "0 = b", (byte) 'b', data[ 0 ] ); file.release( 0, false ); data = file.get( 5 ).getData(); assertEquals( "5 = 0", 0, data[ 5 ] ); file.release( 5, false ); data = file.get( 10 ).getData(); assertEquals( "10 = c", (byte) 'c', data[ 10 ] ); file.release( 10, false ); file.close(); } /** * Test wrong release */ public void testWrongRelease() throws Exception { RecordFile file = new RecordFile( testFileName ); // Write recid 0, byte 0 with 'b' byte[] data = file.get( 0 ).getData(); data[ 0 ] = (byte) 'b'; try { file.release( 1, true ); fail( "expected exception" ); } catch ( IOException except ) { // ignore } file.release( 0, false ); file.close(); // @alex retry to open the file /* file = new RecordFile( testFileName ); PageManager pm = new PageManager( file ); pm.close(); file.close(); */ } /** * Runs all tests in this class */ public static void main( String[] args ) { junit.textui.TestRunner.run( new TestSuite( TestRecordFile.class ) ); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestRecordHeader.java0000644000175000017500000000353010276576000024741 0ustar twernertwerner/* * $Id: TestRecordHeader.java,v 1.2 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for RecordHeader class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.TestCase; import junit.framework.TestSuite; /** * This class contains all Unit tests for {@link RecordHeader}. */ public class TestRecordHeader extends TestCase { public TestRecordHeader(String name) { super(name); } /** * Test basics - read and write at an offset */ public void testReadWrite() throws Exception { byte[] data = new byte[RecordFile.BLOCK_SIZE]; BlockIo test = new BlockIo(0, data); RecordHeader hdr = new RecordHeader(test, (short) 6); hdr.setCurrentSize(1000); hdr.setAvailableSize((short) 2345); assertEquals("current size", 1000, hdr.getCurrentSize()); assertEquals("available size", 2345, hdr.getAvailableSize()); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestRecordHeader.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestRecordManager.java0000644000175000017500000001515010276576000025124 0ustar twernertwerner/* * $Id: TestRecordManager.java,v 1.6 2003/09/21 15:49:02 boisvert Exp $ * * Unit tests for RecordManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import junit.framework.*; /** * This class contains all Unit tests for {@link RecordManager}. */ public class TestRecordManager extends TestCase { public TestRecordManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor */ public void testCtor() throws Exception { RecordManager recman; recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); recman.close(); } /** * Test basics */ public void testBasics() throws Exception { RecordManager recman; recman = new BaseRecordManager( TestRecordFile.testFileName ); // insert a 10,000 byte record. byte[] data = TestUtil.makeRecord(10000, (byte) 1); long rowid = recman.insert(data); assertTrue("check data1", TestUtil.checkRecord( (byte[]) recman.fetch(rowid), 10000, (byte) 1) ); // update it as a 20,000 byte record. data = TestUtil.makeRecord(20000, (byte) 2); recman.update(rowid, data); assertTrue("check data2", TestUtil.checkRecord( (byte[])recman.fetch(rowid), 20000, (byte) 2) ); // insert a third record. data = TestUtil.makeRecord(20, (byte) 3); long rowid2 = recman.insert(data); assertTrue("check data3", TestUtil.checkRecord( (byte[]) recman.fetch(rowid2), 20, (byte) 3) ); // now, grow the first record again data = TestUtil.makeRecord(30000, (byte) 4); recman.update(rowid, data); assertTrue("check data4", TestUtil.checkRecord( (byte[]) recman.fetch(rowid), 30000, (byte) 4) ); // delete the record recman.delete(rowid); // close the file recman.close(); } /** * Test delete and immediate reuse. This attempts to reproduce * a bug in the stress test involving 0 record lengths. */ public void testDeleteAndReuse() throws Exception { RecordManager recman; recman = new BaseRecordManager( TestRecordFile.testFileName ); // insert a 1500 byte record. byte[] data = TestUtil.makeRecord(1500, (byte) 1); long rowid = recman.insert(data); assertTrue("check data1", TestUtil.checkRecord( (byte[]) recman.fetch(rowid), 1500, (byte) 1) ); // delete the record recman.delete(rowid); // insert a 0 byte record. Should have the same rowid. data = TestUtil.makeRecord(0, (byte) 2); long rowid2 = recman.insert(data); assertEquals("old and new rowid", rowid, rowid2); assertTrue("check data2", TestUtil.checkRecord( (byte[]) recman.fetch(rowid2), 0, (byte) 2) ); // now make the record a bit bigger data = TestUtil.makeRecord(10000, (byte) 3); recman.update(rowid, data); assertTrue("check data3", TestUtil.checkRecord( (byte[]) recman.fetch(rowid), 10000, (byte) 3) ); // .. and again data = TestUtil.makeRecord(30000, (byte) 4); recman.update(rowid, data); assertTrue("check data3", TestUtil.checkRecord( (byte[]) recman.fetch(rowid), 30000, (byte) 4) ); // close the file recman.close(); } /** * Test rollback sanity. Attemts to add a new record, rollback and * add the same record. We should obtain the same record id for both * operations. */ public void testRollback() throws Exception { RecordManager recman; // Note: We start out with an empty file recman = new BaseRecordManager( TestRecordFile.testFileName ); // insert a 150000 byte record. byte[] data1 = TestUtil.makeRecord(150000, (byte) 1); long rowid1 = recman.insert(data1); assertTrue("check data1", TestUtil.checkRecord( (byte[]) recman.fetch(rowid1), 150000, (byte) 1) ); // rollback transaction, should revert to previous state recman.rollback(); // insert same 150000 byte record. byte[] data2 = TestUtil.makeRecord(150000, (byte) 1); long rowid2 = recman.insert(data2); assertTrue("check data2", TestUtil.checkRecord( (byte[]) recman.fetch(rowid2), 150000, (byte) 1) ); assertEquals("old and new rowid", rowid1, rowid2); recman.commit(); // insert a 150000 byte record. data1 = TestUtil.makeRecord(150000, (byte) 2); rowid1 = recman.insert(data1); assertTrue("check data1", TestUtil.checkRecord( (byte[]) recman.fetch(rowid1), 150000, (byte) 2) ); // rollback transaction, should revert to previous state recman.rollback(); // insert same 150000 byte record. data2 = TestUtil.makeRecord(150000, (byte) 2); rowid2 = recman.insert(data2); assertTrue("check data2", TestUtil.checkRecord( (byte[]) recman.fetch(rowid2), 150000, (byte) 2) ); assertEquals("old and new rowid", rowid1, rowid2); // close the file recman.close(); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestRecordManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestStress.java0000644000175000017500000002056510276576000023704 0ustar twernertwerner/* * $Id: TestStress.java,v 1.5 2003/09/21 15:49:02 boisvert Exp $ * * Package stress test * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.helper.ByteArraySerializer; import junit.framework.*; import java.util.Random; /** * This class contains stress tests for this package. */ public class TestStress extends TestCase { public TestStress(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } // test parameters final int RECORDS = 10000; final int MAXSIZE = 500; final int ROUNDS = 1 * 1000 * 1000; final int RPPROMILLE = ROUNDS / 1000; Random rnd = new Random(42); // holder for record data so we can compare class RecordData { long rowid; int size; byte b; RecordData(long rowid, int size, byte b) { this.rowid = rowid; this.size = size; this.b = b; } public String toString() { return "slot(" + rowid + ",sz=" + size + ",b=" + b + ")"; } } private int getRandomAllocatedSlot(RecordData[] d) { int slot = rnd.nextInt(RECORDS); while (d[slot] == null) { slot++; if (slot == RECORDS) slot = 0; // wrap } return slot; } // holder for root records long[] roots = new long[FileHeader.NROOTS]; private int getRandomAllocatedRoot() { int slot = rnd.nextInt(FileHeader.NROOTS); while (roots[slot] == 0) { slot++; if (slot == FileHeader.NROOTS) slot = 0; // wrap } return slot; } /** * Test basics */ public void testBasics() throws Exception { RecordManager recman; recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); // as this code is meant to test data structure calculcations // and stuff like that, we may want to disable transactions // that just slow us down. // mgr.disableTransactions(); RecordData[] d = new RecordData[RECORDS]; int recordCount = 0, rootCount = 0; int inserts = 0, updates = 0, deletes = 0, fetches = 0; int rootgets = 0, rootsets = 0; int slot = -1; try { for (int i = 0; i < ROUNDS; i++) { if ((i % RPPROMILLE) == 0) System.out.print("\rComplete: " + i/RPPROMILLE + "/1000th"); // close and re-open a couple of times during the // test, in order to check flushing etcetera. if ((i % (ROUNDS / 5)) == 0) { System.out.print(" (reopened at round " + i/RPPROMILLE + ")"); recman.close(); recman = RecordManagerFactory.createRecordManager( TestRecordFile.testFileName ); // recman.disableTransactions(); } // generate a random number and assign ranges to operations: // 0-10 = insert, 20 = delete, 30-50 = update, 51 = set root, // 52 = get root, rest = fetch. int op = rnd.nextInt(100); if (op <= 10) { // INSERT RECORD if (recordCount == RECORDS) { i -= 1; continue; } slot = 0; while (d[slot] != null) slot++; d[slot] = new RecordData(0, rnd.nextInt(MAXSIZE), (byte) rnd.nextInt()); d[slot].rowid = recman.insert(TestUtil.makeRecord(d[slot].size, d[slot].b)); recordCount++; inserts++; } else if (op == 20) { // DELETE RECORD if (recordCount == 0) { i -= 1; continue; } slot = getRandomAllocatedSlot(d); recman.delete(d[slot].rowid); d[slot] = null; recordCount--; deletes++; } else if (op <= 50) { // UPDATE RECORD if (recordCount == 0) { i -= 1; continue; } slot = getRandomAllocatedSlot(d); d[slot].size = rnd.nextInt(MAXSIZE); d[slot].b = (byte) rnd.nextInt(); recman.update(d[slot].rowid, TestUtil.makeRecord(d[slot].size, d[slot].b)); updates++; } else if (op == 51) { // SET ROOT int root = rnd.nextInt(FileHeader.NROOTS); roots[root] = rnd.nextLong(); recman.setRoot(root, roots[root]); rootsets++; } else if (op == 52) { // GET ROOT if (rootCount == 0) { i -= 1; continue; } int root = getRandomAllocatedRoot(); assertEquals("root", roots[root], recman.getRoot(root)); rootgets++; } else { // FETCH RECORD if (recordCount == 0) { i -= 1; continue; } slot = getRandomAllocatedSlot(d); byte[] data = (byte[]) recman.fetch(d[slot].rowid, ByteArraySerializer.INSTANCE ); assertTrue("fetch round=" + i + ", slot=" + slot + ", " + d[slot], TestUtil.checkRecord(data, d[slot].size, d[slot].b)); fetches++; } } recman.close(); } catch (Throwable e) { e.printStackTrace(); fail("aborting test at slot " + slot + ": " + e); } finally { System.out.println("records : " + recordCount); System.out.println("deletes : " + deletes); System.out.println("inserts : " + inserts); System.out.println("updates : " + updates); System.out.println("fetches : " + fetches); System.out.println("rootget : " + rootgets); System.out.println("rootset : " + rootsets); int totalSize = 0; for (int i = 0; i < RECORDS; i++) if (d[i] != null) totalSize += d[i].size; System.out.println("total outstanding size: " + totalSize); //System.out.println("---"); //for (int i = 0; i < RECORDS; i++) // if (d[i] != null) // System.out.println("slot " + i + ": " + d[i]); } } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestStress.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestTransactionManager.java0000644000175000017500000001072010276576000026171 0ustar twernertwerner/* * $Id: TestTransactionManager.java,v 1.4 2003/08/07 06:53:58 boisvert Exp $ * * Unit tests for TransactionManager class * * Simple db toolkit * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; import junit.framework.*; import java.io.*; /** * This class contains all Unit tests for {@link TransactionManager}. */ public class TestTransactionManager extends TestCase { public TestTransactionManager(String name) { super(name); } public void setUp() { TestRecordFile.deleteTestFile(); } public void tearDown() { TestRecordFile.deleteTestFile(); } /** * Test constructor. Oops - can only be done indirectly :-) */ public void testCtor() throws Exception { RecordFile file = new RecordFile(TestRecordFile.testFileName); file.forceClose(); } /** * Test recovery */ public void XtestRecovery() throws Exception { RecordFile file1 = new RecordFile(TestRecordFile.testFileName); // Do three transactions. for (int i = 0; i < 3; i++) { BlockIo node = file1.get(i); node.setDirty(); file1.release(node); file1.commit(); } assertDataSizeEquals("len1", 0); assertLogSizeNotZero("len1"); file1.forceClose(); // Leave the old record file in flux, and open it again. // The second instance should start recovery. RecordFile file2 = new RecordFile(TestRecordFile.testFileName); assertDataSizeEquals("len2", 3 * RecordFile.BLOCK_SIZE); assertLogSizeEquals("len2", 8); file2.forceClose(); // assure we can recover this log file RecordFile file3 = new RecordFile(TestRecordFile.testFileName); file3.forceClose(); } /** * Test background synching */ public void XtestSynching() throws Exception { RecordFile file1 = new RecordFile(TestRecordFile.testFileName); // Do enough transactions to fill the first slot int txnCount = TransactionManager.DEFAULT_TXNS_IN_LOG + 5; for (int i = 0; i < txnCount; i++) { BlockIo node = file1.get(i); node.setDirty(); file1.release(node); file1.commit(); } file1.forceClose(); // The data file now has the first slotfull assertDataSizeEquals("len1", TransactionManager.DEFAULT_TXNS_IN_LOG * RecordFile.BLOCK_SIZE); assertLogSizeNotZero("len1"); // Leave the old record file in flux, and open it again. // The second instance should start recovery. RecordFile file2 = new RecordFile(TestRecordFile.testFileName); assertDataSizeEquals("len2", txnCount * RecordFile.BLOCK_SIZE); assertLogSizeEquals("len2", 8); file2.forceClose(); } // Helpers void assertDataSizeEquals(String msg, long size) { assertEquals(msg + " data size", size, new File(TestRecordFile.testFileName + RecordFile.extension).length()); } void assertLogSizeEquals(String msg, long size) { assertEquals(msg + " log size", size, new File(TestRecordFile.testFileName + TransactionManager.extension).length()); } void assertLogSizeNotZero(String msg) { assertTrue(msg + " log size", new File(TestRecordFile.testFileName + TransactionManager.extension).length() != 0); } /** * Runs all tests in this class */ public static void main(String[] args) { junit.textui.TestRunner.run(new TestSuite(TestTransactionManager.class)); } } libjdbm-java-1.0.orig/src/tests/jdbm/recman/TestUtil.java0000644000175000017500000000350410276576000023330 0ustar twernertwerner/* * $Id: TestUtil.java,v 1.1 2000/05/06 00:00:53 boisvert Exp $ * * Unit test utilities. * * Simple db toolkit. * Copyright (C) 1999, 2000 Cees de Groot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package jdbm.recman; /** * This class contains some test utilities. */ public class TestUtil { /** * Creates a "record" containing "length" repetitions of the * indicated byte. */ public static byte[] makeRecord(int length, byte b) { byte[] retval = new byte[length]; for (int i = 0; i < length; i++) retval[i] = b; return retval; } /** * Checks whether the record has the indicated length and data */ public static boolean checkRecord(byte[] data, int length, byte b) { if (data.length != length) { System.err.println("length doesn't match: expected " + length + ", got " + data.length); return false; } for (int i = 0; i < length; i++) if (data[i] != b) { System.err.println("byte " + i + " wrong: expected " + b + ", got " + data[i]); return false; } return true; } } libjdbm-java-1.0.orig/src/tests/jdbm/AllTests.java0000644000175000017500000000576510276576000022054 0ustar twernertwerner/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright * statements and notices. Redistributions must also contain a * copy of this document. * * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote * products derived from this Software without prior written * permission of Cees de Groot. For written permission, * please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" * nor may "JDBM" appear in their names without prior written * permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project * (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id */ package jdbm; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Top level test for JDBM that aggregates subpackage tests in the proper * (dependency) order. * * @author Dilum Ranatunga * @version $Id: AllTests.java,v 1.1 2003/10/30 23:13:01 dranatunga Exp $ */ public class AllTests extends TestCase { public AllTests(String name) { super(name); } /** * Aggregate of the follows suites, in the order listed: *
    *
  1. {@link jdbm.helper.Test}
  2. *
  3. {@link jdbm.recman.Test}
  4. *
  5. {@link jdbm.btree.Test}
  6. *
  7. {@link jdbm.htree.Test}
  8. *
*/ public static junit.framework.Test suite() { TestSuite suite = new TestSuite(); suite.addTest(jdbm.helper.Test.suite()); suite.addTest(jdbm.recman.Test.suite()); suite.addTest(jdbm.btree.Test.suite()); suite.addTest(jdbm.htree.Test.suite()); return suite; } } libjdbm-java-1.0.orig/src/tests/jdbm/CrashTest.java0000644000175000017500000000645010276576000022211 0ustar twernertwerner package jdbm; import jdbm.RecordManager; import jdbm.htree.HTree; import java.io.IOException; /** * Sample JDBM application to demonstrate the use of basic JDBM operations * * @author Alex Boisvert * @version $Id: CrashTest.java,v 1.7 2002/05/31 06:34:29 boisvert Exp $ */ public class CrashTest { private RecordManager _recman; private HTree _htree; public CrashTest() { try { _recman = RecordManagerFactory.createRecordManager( "crashtest" ); // create or reload HTree long recid = _recman.getNamedObject( "htree" ); if ( recid == 0 ) { _htree = HTree.createInstance( _recman ); _recman.setNamedObject( "htree", _htree.getRecid() ); } else { _htree = HTree.load( _recman, recid ); } checkConsistency(); while (true) { Integer countInt = (Integer)_htree.get("count"); if (countInt == null) { System.out.println("Create new crash test"); countInt = new Integer(0); } int count = countInt.intValue(); System.out.print(","+count); System.out.flush(); int mod = count % 2; int delete_window = 20; int update_window = 10; if ((mod) == 0) { // create some entries for (int i=0; i<10; i++) { String id = " "+count+"-"+i; _htree.put("key"+id, "value"+id); } // delete some entries if (count > delete_window) { for (int i=0; i<10; i++) { String id = " "+(count-delete_window)+"-"+i; _htree.remove("key"+id); } } } else if ((mod) == 1) { if (count > update_window+1) { // update some stuff for (int i=0; i<5; i++) { String id = " "+(count-update_window+1)+"-"+i; String s = (String)_htree.get("key"+id); if ((s == null) || !s.equals("value"+id)) { throw new Error("Invalid value. Expected: " +("value"+id) +", got: " +s); } _htree.put("key"+id, s+"-updated"); } } } _htree.put("count", new Integer(count+1)); _recman.commit(); count++; } // BTW: There is no cleanup. It's a crash test after all. } catch (IOException ioe) { ioe.printStackTrace(); } } void checkConsistency() { // TODO } public static void main(String[] args) { System.out.print("Please try to stop me anytime. "); System.out.println("CTRL-C, kill -9, anything goes!."); new CrashTest(); } } libjdbm-java-1.0.orig/src/tests/jdbm/HashtableTest.java0000644000175000017500000001104210276576000023035 0ustar twernertwerner package jdbm; import jdbm.RecordManager; import jdbm.RecordManagerFactory; import jdbm.helper.FastIterator; import jdbm.htree.HTree; import java.io.IOException; import java.io.PrintStream; /** * Test case provided by Daniel Herlemont to demonstrate a bug in * HashDirectory. The returned Enumeration got into an infinite loop * on the same key/val pair. * * @version $Id: HashtableTest.java,v 1.6 2005/06/25 23:12:32 doomdark Exp $ */ public class HashtableTest { private RecordManager recman; private HTree hashtable; private boolean enumerate = false; private boolean populate = false; private boolean retrieve = false; private String jdbmName = "hashtest"; private String name = "hashtable"; private String onekey = "onekey"; /** * Initialize RecordManager and HTree */ protected void init() throws IOException { recman = RecordManagerFactory.createRecordManager( jdbmName ); // create or reload HTree long recid = recman.getNamedObject( name ); if ( recid == 0 ) { hashtable = HTree.createInstance( recman ); recman.setNamedObject( name, hashtable.getRecid() ); } else { hashtable = HTree.load( recman, recid ); } } /** * Populate HTree with some data */ protected void populate() throws IOException { try { int max = 1000; for ( int i=0; i