You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2013/01/18 11:10:57 UTC
svn commit: r1435064 [5/7] - in /directory/jdbm/trunk/jdbm1: ./ src/
src/etc/ src/examples/ src/main/ src/main/java/ src/main/java/jdbm/
src/main/java/jdbm/btree/ src/main/java/jdbm/helper/
src/main/java/jdbm/htree/ src/main/java/jdbm/recman/ src/main/...
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FileHeader.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FileHeader.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FileHeader.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FileHeader.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,184 @@
+/**
+ * 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;
+
+
+import java.io.IOException;
+
+import jdbm.I18n;
+
+
+/**
+ * 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 ( block.readShort( O_MAGIC ) != Magic.FILE_HEADER )
+ {
+ throw new Error( I18n.err( I18n.ERR_544, block.readShort( O_MAGIC ) ) );
+ }
+ }
+
+
+ /**
+ * 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 );
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPage.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPage.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPage.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPage.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,161 @@
+/**
+ * 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 = O_COUNT + Magic.SZ_SHORT;
+ static final short ELEMS_PER_PAGE = ( 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;
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPageManager.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPageManager.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPageManager.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreeLogicalRowIdPageManager.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,142 @@
+/**
+ * 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 recordFile
+ private RecordFile recordFile;
+ // our page manager
+ private PageManager pageManager;
+
+ /**
+ * Creates a new instance using the indicated record file and
+ * page manager.
+ */
+ FreeLogicalRowIdPageManager( PageManager pageManager) throws IOException {
+ this.pageManager = pageManager;
+ this.recordFile = pageManager.getRecordFile();
+ }
+
+ /**
+ * 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(pageManager, Magic.FREELOGIDS_PAGE);
+ while (curs.next() != 0) {
+ FreeLogicalRowIdPage fp = FreeLogicalRowIdPage
+ .getFreeLogicalRowIdPageView(recordFile.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
+ recordFile.release(curs.getCurrent(), false);
+ pageManager.free(Magic.FREELOGIDS_PAGE, curs.getCurrent());
+ }
+ else
+ recordFile.release(curs.getCurrent(), true);
+
+ return retval;
+ }
+ else {
+ // no luck, go to next page
+ recordFile.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(pageManager, Magic.FREELOGIDS_PAGE);
+ long freePage = 0;
+ while (curs.next() != 0) {
+ freePage = curs.getCurrent();
+ BlockIo curBlock = recordFile.get(freePage);
+ FreeLogicalRowIdPage fp = FreeLogicalRowIdPage
+ .getFreeLogicalRowIdPageView(curBlock);
+ int slot = fp.getFirstFree();
+ if (slot != -1) {
+ free = fp.alloc(slot);
+ break;
+ }
+
+ recordFile.release(curBlock);
+ }
+ if (free == null) {
+ // No more space on the free list, add a page.
+ freePage = pageManager.allocate(Magic.FREELOGIDS_PAGE);
+ BlockIo curBlock = recordFile.get(freePage);
+ FreeLogicalRowIdPage fp =
+ FreeLogicalRowIdPage.getFreeLogicalRowIdPageView(curBlock);
+ free = fp.alloc(0);
+ }
+ free.setBlock(rowid.getBlock());
+ free.setOffset(rowid.getOffset());
+ recordFile.release(freePage, true);
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowId.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowId.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowId.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowId.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,83 @@
+/**
+ * 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 indicate
+ * 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 );
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPage.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPage.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPage.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPage.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,186 @@
+/**
+ * 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;
+ }
+}
\ No newline at end of file
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPageManager.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPageManager.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPageManager.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/FreePhysicalRowIdPageManager.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,161 @@
+/**
+ * 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 at a high level.
+ */
+final class FreePhysicalRowIdPageManager
+{
+ // our record recordFile
+ protected RecordFile recordFile;
+
+ // our page manager
+ protected PageManager pageManager;
+
+
+ /**
+ * Creates a new instance using the indicated record recordFile and page manager.
+ */
+ FreePhysicalRowIdPageManager( PageManager pageManager ) throws IOException
+ {
+ this.recordFile = pageManager.getRecordFile();
+ this.pageManager = pageManager;
+ }
+
+
+ /**
+ * 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( pageManager, Magic.FREEPHYSIDS_PAGE );
+
+ while ( curs.next() != 0 )
+ {
+ FreePhysicalRowIdPage fp = FreePhysicalRowIdPage
+ .getFreePhysicalRowIdPageView( recordFile.get( curs.getCurrent() ) );
+ int slot = fp.getFirstLargerThan( size );
+
+ if ( slot != -1 )
+ {
+ // got one!
+ retval = new Location( fp.get( slot ) );
+
+ fp.free( slot );
+ if ( fp.getCount() == 0 )
+ {
+ // page became empty - free it
+ recordFile.release( curs.getCurrent(), false );
+ pageManager.free( Magic.FREEPHYSIDS_PAGE, curs.getCurrent() );
+ }
+ else
+ {
+ recordFile.release( curs.getCurrent(), true );
+ }
+
+ return retval;
+ }
+ else
+ {
+ // no luck, go to next page
+ recordFile.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( pageManager, Magic.FREEPHYSIDS_PAGE );
+ long freePage = 0;
+
+ while ( curs.next() != 0 )
+ {
+ freePage = curs.getCurrent();
+ BlockIo curBlock = recordFile.get( freePage );
+ FreePhysicalRowIdPage fp = FreePhysicalRowIdPage.getFreePhysicalRowIdPageView( curBlock );
+ int slot = fp.getFirstFree();
+
+ if ( slot != -1 )
+ {
+ free = fp.alloc( slot );
+ break;
+ }
+
+ recordFile.release( curBlock );
+ }
+
+ if ( free == null )
+ {
+ // No more space on the free list, add a page.
+ freePage = pageManager.allocate( Magic.FREEPHYSIDS_PAGE );
+ BlockIo curBlock = recordFile.get( freePage );
+ FreePhysicalRowIdPage fp = FreePhysicalRowIdPage.getFreePhysicalRowIdPageView( curBlock );
+ free = fp.alloc( 0 );
+ }
+
+ free.setBlock( rowid.getBlock() );
+ free.setOffset( rowid.getOffset() );
+ free.setSize( size );
+ recordFile.release( freePage, true );
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Location.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Location.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Location.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Location.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,153 @@
+/**
+ * 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. A recid is a logical rowid.
+ */
+ 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;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode()
+ {
+ return 663;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ 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()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append( "Location ( " ).append( block ).append( " : " );
+ sb.append( offset ).append( " ) " );
+ return sb.toString();
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/LogicalRowIdManager.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/LogicalRowIdManager.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/LogicalRowIdManager.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/LogicalRowIdManager.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,158 @@
+/**
+ * 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;
+
+import jdbm.I18n;
+
+
+/**
+ * This class manages the linked lists of logical rowid pages.
+ */
+final class LogicalRowIdManager
+{
+ // our record recordFile and associated page manager
+ private RecordFile recordFile;
+ private PageManager pageManager;
+ private FreeLogicalRowIdPageManager freeman;
+
+
+ /**
+ * Creates a log rowid manager using the indicated record recordFile and
+ * page manager
+ */
+ LogicalRowIdManager( PageManager pageManager ) throws IOException
+ {
+ this.recordFile = pageManager.getRecordFile();
+ this.pageManager = pageManager;
+ this.freeman = new FreeLogicalRowIdPageManager( pageManager );
+ }
+
+
+ /**
+ * 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 = pageManager.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( I18n.err( I18n.ERR_545 ) );
+ }
+ }
+ // 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( recordFile.get( rowid.getBlock() ) );
+ PhysicalRowId physid = xlatPage.get( rowid.getOffset() );
+ physid.setBlock( loc.getBlock() );
+ physid.setOffset( loc.getOffset() );
+ recordFile.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( recordFile.get( rowid.getBlock() ) );
+ try
+ {
+ Location retval = new Location( xlatPage.get( rowid.getOffset() ) );
+ return retval;
+ }
+ finally
+ {
+ recordFile.release( rowid.getBlock(), false );
+ }
+ }
+
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Magic.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Magic.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Magic.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/Magic.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ * Final reference -> class shouldn't be extended
+ */
+public final class Magic
+{
+ /**
+ * Ensures no construction of this class, also ensures there is no need for final keyword above
+ * (Implicit super constructor is not visible for default constructor),
+ * but is still self documenting.
+ */
+ private Magic()
+ {
+ }
+
+
+ /** Magic cookie at start of file */
+ public final static short FILE_HEADER = 0x1350;
+
+ /** Magic for blocks. They're offset by the block type magic codes. */
+ public final static short BLOCK = 0x1351;
+
+ /** Magics for block types in certain lists. Offset by baseBlockMagic */
+ public final static short FREE_PAGE = 0;
+ public final static short USED_PAGE = 1;
+ public final static short TRANSLATION_PAGE = 2;
+ public final static short FREELOGIDS_PAGE = 3;
+ public final static short FREEPHYSIDS_PAGE = 4;
+
+ /** Number of lists in a file */
+ public final static short NLISTS = 5;
+
+ /**
+ * Maximum number of blocks in a file, leaving room for a 16 bit
+ * offset encoded within a long.
+ */
+ public final static long MAX_BLOCKS = 0x7FFFFFFFFFFFL;
+
+ /** Magic for transaction file */
+ public final static short LOGFILE_HEADER = 0x1360;
+
+ /** Size of an externalized byte */
+ public final static short SZ_BYTE = 1;
+ /** Size of an externalized short */
+ public final static short SZ_SHORT = 2;
+ /** Size of an externalized int */
+ public final static short SZ_INT = 4;
+ /** Size of an externalized long */
+ public final static short SZ_LONG = 8;
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageCursor.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageCursor.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageCursor.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageCursor.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,119 @@
+/**
+ * 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;
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageHeader.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageHeader.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageHeader.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageHeader.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,198 @@
+/**
+ * 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;
+
+
+import java.io.IOException;
+
+import jdbm.I18n;
+
+
+/**
+ * This class represents a page header. It is the common superclass for
+ * all different page views. It contains the following information:
+ *
+ * <ol>
+ * <li>2 bytes: the short block type code</li>
+ * <li>8 bytes: the long block id of the next block in the block list</li>
+ * <li>8 bytes: the long block id of the previous block in the block list</li>
+ * </ol>
+ *
+ * The page header block view hence sees 18 bytes of page header data.
+ */
+public class PageHeader implements BlockView
+{
+ // offsets into page header's (BlockIo's) buffer
+
+ /** the page (BlockIo's type code) short magic code */
+ private static final short O_MAGIC = 0;
+ /** the long block id of the next block in the block list */
+ private static final short O_NEXT = Magic.SZ_SHORT;
+ /** the long block id of the previous block in the block list */
+ private static final short O_PREV = O_NEXT + Magic.SZ_LONG;
+
+ /** the size of this page header = 18 bytes */
+ protected static final short SIZE = O_PREV + Magic.SZ_LONG;
+
+ /** the page header block this view is associated with */
+ protected BlockIo block;
+
+
+ /**
+ * Constructs a PageHeader object from a block
+ *
+ * @param block The block that contains the page header
+ * @throws IOException if the block is too short to keep the page header.
+ */
+ protected PageHeader( BlockIo block )
+ {
+ this.block = block;
+ block.setView( this );
+ if ( !magicOk() )
+ {
+ throw new Error( I18n.err( I18n.ERR_546, block.getBlockId(), getMagic() ) );
+ }
+ }
+
+
+ /**
+ * Constructs a new PageHeader of the indicated type. Used for newly
+ * created pages.
+ */
+ PageHeader( BlockIo block, short type )
+ {
+ this.block = block;
+ block.setView( this );
+ 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 );
+ }
+ }
+
+
+ /**
+ * 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( I18n.err( I18n.ERR_547, 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 ) );
+ }
+}
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageManager.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageManager.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageManager.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PageManager.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,349 @@
+/**
+ * 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.IOException;
+
+import jdbm.I18n;
+
+
+/**
+ * This class manages the linked lists of pages that make up a recordFile.
+ */
+final class PageManager
+{
+ // our record recordFile
+ private RecordFile recordFile;
+
+ // header data
+ private FileHeader header;
+
+ // recordFile header containing block
+ private BlockIo headerBuf;
+
+
+ /**
+ * Creates a new page manager using the indicated record recordFile.
+ */
+ PageManager( RecordFile recordFile ) throws IOException
+ {
+ this.recordFile = recordFile;
+
+ // Note that we hold on to the recordFile header node.
+ headerBuf = recordFile.get( 0 );
+
+ // Assume recordFile is new if the recordFile header's magic number is 0.
+ if ( headerBuf.readShort( 0 ) == 0 )
+ {
+ header = new FileHeader( headerBuf, true );
+ }
+ else
+ // header is for existing recordFile
+ {
+ 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( I18n.err( I18n.ERR_548 ) );
+ }
+
+ boolean isNew = false;
+
+ // Do we have something on the free list?
+ long retval = header.getFirstOf( Magic.FREE_PAGE );
+ 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 recordFile - 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 = recordFile.get( retval );
+ PageHeader pageHdr = null;
+
+ if ( isNew )
+ {
+ pageHdr = new PageHeader( buf, type );
+ }
+ else
+ {
+ pageHdr = 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 );
+ recordFile.release( retval, true );
+
+ // If there's a previous, fix up its pointer
+ if ( oldLast != 0 )
+ {
+ buf = recordFile.get( oldLast );
+ pageHdr = PageHeader.getView( buf );
+ pageHdr.setNext( retval );
+ recordFile.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( I18n.err( I18n.ERR_549 ) );
+ }
+
+ if ( recid == 0 )
+ {
+ throw new Error( I18n.err( I18n.ERR_550 ) );
+ }
+
+ // get the page and read next and previous pointers
+ BlockIo buf = recordFile.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 );
+ recordFile.release( recid, true );
+
+ // remove the page from its old list
+ if ( prev != 0 )
+ {
+ buf = recordFile.get( prev );
+ pageHdr = PageHeader.getView( buf );
+ pageHdr.setNext( next );
+ recordFile.release( prev, true );
+ }
+ else
+ {
+ header.setFirstOf( type, next );
+ }
+
+ if ( next != 0 )
+ {
+ buf = recordFile.get( next );
+ pageHdr = PageHeader.getView( buf );
+ pageHdr.setPrev( prev );
+ recordFile.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( recordFile.get( block ) ).getNext();
+ }
+ finally
+ {
+ recordFile.release( block, false );
+ }
+ }
+
+
+ /**
+ * Returns the page before the indicated block
+ */
+ long getPrev( long block ) throws IOException
+ {
+ try
+ {
+ return PageHeader.getView( recordFile.get( block ) ).getPrev();
+ }
+ finally
+ {
+ recordFile.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 is an implicit
+ * {@link RecordFile#commit} as well).
+ */
+ void commit() throws IOException
+ {
+ // write the header out
+ recordFile.release( headerBuf );
+ recordFile.commit();
+
+ // and obtain it again
+ headerBuf = recordFile.get( 0 );
+ header = new FileHeader( headerBuf, false );
+ }
+
+
+ /**
+ * Flushes the page manager. This forces a flush of all outstanding
+ * blocks (this is an implicit {@link RecordFile#commit} as well).
+ *
+ * @TODO completely wrong description of method
+ */
+ void rollback() throws IOException
+ {
+ // release header
+ recordFile.discard( headerBuf );
+ recordFile.rollback();
+ // and obtain it again
+ headerBuf = recordFile.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
+ {
+ recordFile.release( headerBuf );
+ recordFile.commit();
+ headerBuf = null;
+ header = null;
+ recordFile = null;
+ }
+
+
+ /**
+ * Returns the recordFile header.
+ */
+ FileHeader getFileHeader()
+ {
+ return header;
+ }
+
+
+ RecordFile getRecordFile()
+ {
+ return recordFile;
+ }
+}
\ No newline at end of file
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowId.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowId.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowId.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowId.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,106 @@
+/**
+ * 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.
+ * <P>
+ * <B>Note</B>: The fact that the offset is modeled 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 );
+ }
+}
\ No newline at end of file
Added: directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowIdManager.java
URL: http://svn.apache.org/viewvc/directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowIdManager.java?rev=1435064&view=auto
==============================================================================
--- directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowIdManager.java (added)
+++ directory/jdbm/trunk/jdbm1/src/main/java/jdbm/recman/PhysicalRowIdManager.java Fri Jan 18 10:10:55 2013
@@ -0,0 +1,339 @@
+/**
+ * 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 pageManager;
+ private FreePhysicalRowIdPageManager freeman;
+
+ /**
+ * Creates a new rowid manager using the indicated record file.
+ * and page manager.
+ */
+ PhysicalRowIdManager( PageManager pageManager )
+ throws IOException
+ {
+ this.pageManager = pageManager;
+ this.file = pageManager.getRecordFile();
+ this.freeman = new FreePhysicalRowIdPageManager( pageManager );
+ }
+
+ /**
+ * 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 = pageManager.getRecordFile().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.
+ pageManager.getRecordFile().release( block );
+ free( rowid );
+ rowid = alloc( length );
+ } else {
+ pageManager.getRecordFile().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( pageManager, 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 ) {
+ // temporary work around for DIRSERVER-1459
+ retval = allocNew( size * 2, pageManager.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 = pageManager.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 = pageManager.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 = pageManager.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() );
+ 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( pageManager, 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;
+ }
+ }
+ }
+}
+