avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l...@apache.org
Subject cvs commit: jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/test TableIdGeneratorJdbcTestCase.java TableIdGeneratorJdbcTestCase.xtest
Date Fri, 08 Feb 2002 17:38:09 GMT
leif        02/02/08 09:38:09

  Modified:    src/scratchpad/org/apache/avalon/excalibur/datasource/ids
                        AbstractDataSourceBlockIdGenerator.java
                        AbstractDataSourceIdGenerator.java
                        TableIdGenerator.java
               src/scratchpad/org/apache/avalon/excalibur/datasource/ids/test
                        TableIdGeneratorJdbcTestCase.java
                        TableIdGeneratorJdbcTestCase.xtest
  Log:
  Fix some problems with IdGenerator and make things work with MySQL databases.
  
  Revision  Changes    Path
  1.2       +8 -1      jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/AbstractDataSourceBlockIdGenerator.java
  
  Index: AbstractDataSourceBlockIdGenerator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/AbstractDataSourceBlockIdGenerator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractDataSourceBlockIdGenerator.java	8 Feb 2002 12:27:32 -0000	1.1
  +++ AbstractDataSourceBlockIdGenerator.java	8 Feb 2002 17:38:09 -0000	1.2
  @@ -22,7 +22,7 @@
    *  the DataSource.
    *
    * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
  - * @version CVS $Revision: 1.1 $ $Date: 2002/02/08 12:27:32 $
  + * @version CVS $Revision: 1.2 $ $Date: 2002/02/08 17:38:09 $
    * @since 4.1
    */
   public abstract class AbstractDataSourceBlockIdGenerator
  @@ -152,6 +152,13 @@
           // We know that at least one id is available.
           // Get an id out of the currently allocated block.
           long id = m_firstLong + m_allocated;
  +        if ( id < 0 )
  +        {
  +            // The value wrapped
  +            String msg = "No more Ids are available, the maximum long value has been reached.";
  +            getLogger().error( msg );
  +            throw new IdException( msg );
  +        }
           m_allocated++;
           
           return id;
  
  
  
  1.2       +33 -1     jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/AbstractDataSourceIdGenerator.java
  
  Index: AbstractDataSourceIdGenerator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/AbstractDataSourceIdGenerator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractDataSourceIdGenerator.java	8 Feb 2002 12:27:32 -0000	1.1
  +++ AbstractDataSourceIdGenerator.java	8 Feb 2002 17:38:09 -0000	1.2
  @@ -9,6 +9,7 @@
   
   import java.math.BigDecimal;
   import java.sql.Connection;
  +import java.sql.Statement;
   import java.sql.SQLException;
   
   import org.apache.avalon.excalibur.datasource.DataSourceComponent;
  @@ -26,19 +27,23 @@
   
   /**
    * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
  - * @version CVS $Revision: 1.1 $ $Date: 2002/02/08 12:27:32 $
  + * @version CVS $Revision: 1.2 $ $Date: 2002/02/08 17:38:09 $
    * @since 4.1
    */
   public abstract class AbstractDataSourceIdGenerator
       extends AbstractIdGenerator
       implements IdGenerator, Composable, Configurable, Initializable, Disposable, ThreadSafe
   {
  +    protected static final int DBTYPE_STANDARD = 0;
  +    protected static final int DBTYPE_MYSQL    = 1;
  +    
       /** ComponentManager which created this component */
       protected ComponentManager    m_manager;
   
       private   String              m_dataSourceName;
       private   ComponentSelector   m_dbSelector;
       protected DataSourceComponent m_dataSource;
  +    protected int                 m_dbType;
       
       /**
        * Number of allocated Ids remaining before another block must be allocated.
  @@ -116,6 +121,33 @@
           // Get a reference to a data source
           m_dbSelector = (ComponentSelector)m_manager.lookup( DataSourceComponent.ROLE +
"Selector" );
           m_dataSource = (DataSourceComponent)m_dbSelector.select( m_dataSourceName );
  +        
  +        // Resolve the type of database that is being used.
  +        try
  +        {
  +            Connection conn = getConnection();
  +            try
  +            {
  +                Statement statement = conn.createStatement();
  +                String className = statement.getClass().getName();
  +                if ( className.indexOf( "mysql" ) > 0 )
  +                {
  +                    m_dbType = DBTYPE_MYSQL;
  +                }
  +                else
  +                {
  +                    m_dbType = DBTYPE_STANDARD;
  +                }
  +            }
  +            finally
  +            {
  +                conn.close();
  +            }
  +        }
  +        catch (SQLException e)
  +        {
  +            getLogger().error( "Unable to open connection to resolve database type.", e
);
  +        }
       }
   
       /*---------------------------------------------------------------
  
  
  
  1.2       +133 -3    jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/TableIdGenerator.java
  
  Index: TableIdGenerator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/TableIdGenerator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TableIdGenerator.java	8 Feb 2002 12:27:32 -0000	1.1
  +++ TableIdGenerator.java	8 Feb 2002 17:38:09 -0000	1.2
  @@ -57,9 +57,18 @@
    *
    * Your component obtains a reference to an IdGenerator using the same method as it obtains
a
    *  DataSource, by making use of a ComponentSelector.
  + * <p>
  + * Depending on your database, the ids table should look something like the following:
  + * <pre>
  + *   CREATE TABLE ids (
  + *       table_name varchar(16) NOT NULL,
  + *       next_id INTEGER NOT NULL,
  + *       PRIMARY KEY (table_name)
  + *   );
  + * </pre>
    *
    * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
  - * @version CVS $Revision: 1.1 $ $Date: 2002/02/08 12:27:32 $
  + * @version CVS $Revision: 1.2 $ $Date: 2002/02/08 17:38:09 $
    * @since 4.1
    */
   public class TableIdGenerator
  @@ -236,6 +245,105 @@
           }
       }
       
  +    /**
  +     * Allocates a block of ids of the given size and returns the first id.
  +     *  MySQL does not support transactions so this method handles synchronization
  +     *  by making use of table locking.
  +     *
  +     * @param blockSize number of ids to allocate.
  +     * @param useBigDecimals returns the first id as a BigDecimal if true, otherwise as
a Long.
  +     *
  +     * @returns either a Long or a BigDecimal depending on the value of useBigDecimals
  +     *
  +     * @throws IdException if a block of ids can not be allocated.
  +     */
  +    private Object allocateIdBlockMySQL( int blockSize, boolean useBigDecimals )
  +        throws IdException
  +    {
  +        if ( getLogger().isDebugEnabled() )
  +        {
  +            getLogger().debug( "Allocating a new block of " + blockSize + " ids." );
  +        }
  +        
  +        try
  +        {
  +            Connection conn = getConnection();
  +            try
  +            {
  +                Statement stmt = conn.createStatement();
  +                
  +                // Obtain a lock on the table
  +                stmt.executeUpdate( "LOCK TABLES " + m_table + " WRITE" );
  +                try
  +                {
  +                    // Get the nextId from the table
  +                    ResultSet rs = stmt.executeQuery(
  +                        "SELECT next_id FROM " + m_table + " WHERE table_name = '" + m_tableName
+ "'" );
  +                    if ( !rs.next() )
  +                    {
  +                        // The row does not exist.
  +                        String msg = "Unable to allocate a block of Ids, no row with table_name='"
+
  +                            m_tableName + "' exists in the " + m_table + " table.";
  +                        getLogger().error( msg );
  +                        
  +                        throw new IdException( msg );
  +                    }
  +                    
  +                    // Get the next_id using the appropriate data type.
  +                    Object nextId;
  +                    Object nextSavedId;
  +                    if ( useBigDecimals )
  +                    {
  +                        BigDecimal id = rs.getBigDecimal( 1 );
  +                        nextId = id;
  +                        nextSavedId = id.add( new BigDecimal( blockSize ) );
  +                    }
  +                    else
  +                    {
  +                        Long id = new Long( rs.getLong( 1 ) );
  +                        nextId = id;
  +                        nextSavedId = new Long( id.longValue() + blockSize );
  +                    }
  +                    
  +                    // Update the value of next_id in the database so it reflects the full
block
  +                    //  being allocated.
  +                    //
  +                    // Queries that set next_id = next_id + 10 do not work with large decimal
values on MySQL 3.23.31
  +                    int updated = stmt.executeUpdate( "UPDATE " + m_table + 
  +                        " SET next_id = " + nextSavedId + 
  +                        " WHERE table_name = '" + m_tableName + "'" );
  +                    if ( updated >= 1 )
  +                    {
  +                        // Return the next id obtained above.
  +                        return nextId;
  +                    }
  +                    else
  +                    {
  +                        String msg = "Update resulted in no rows being changed.";
  +                        getLogger().error( msg );
  +                    
  +                        throw new IdException( msg );
  +                    }
  +                }
  +                finally
  +                {
  +                    // Make absolutely sure that the lock is always released.
  +                    stmt.executeUpdate( "UNLOCK TABLES" );
  +                }
  +            }
  +            finally
  +            {
  +                conn.close();
  +            }
  +        }
  +        catch (SQLException e)
  +        {
  +            String msg = "Unable to allocate a block of Ids.";
  +            getLogger().error( msg, e );
  +            throw new IdException( msg, e );
  +        }
  +    }
  +    
       /*---------------------------------------------------------------
        * AbstractDataSourceBlockIdGenerator Methods
        *-------------------------------------------------------------*/
  @@ -251,7 +359,18 @@
       protected BigDecimal allocateBigDecimalIdBlock( int blockSize )
           throws IdException
       {
  -        return (BigDecimal)allocateIdBlock( blockSize, true );
  +        BigDecimal id;
  +        switch( m_dbType )
  +        {
  +        case AbstractDataSourceIdGenerator.DBTYPE_MYSQL:
  +            id = (BigDecimal)allocateIdBlockMySQL( blockSize, true );
  +            break;
  +            
  +        default:
  +            id = (BigDecimal)allocateIdBlock( blockSize, true );
  +        }
  +        
  +        return id;
       }
       
       /**
  @@ -266,7 +385,18 @@
       protected long allocateLongIdBlock( int blockSize )
           throws IdException
       {
  -        return ((Long)allocateIdBlock( blockSize, false )).longValue();
  +        Long id;
  +        switch( m_dbType )
  +        {
  +        case AbstractDataSourceIdGenerator.DBTYPE_MYSQL:
  +            id = (Long)allocateIdBlockMySQL( blockSize, false );
  +            break;
  +            
  +        default:
  +            id = (Long)allocateIdBlock( blockSize, false );
  +        }
  +        
  +        return id.longValue();
       }
       
       /*---------------------------------------------------------------
  
  
  
  1.2       +88 -27    jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/test/TableIdGeneratorJdbcTestCase.java
  
  Index: TableIdGeneratorJdbcTestCase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/test/TableIdGeneratorJdbcTestCase.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TableIdGeneratorJdbcTestCase.java	8 Feb 2002 12:27:32 -0000	1.1
  +++ TableIdGeneratorJdbcTestCase.java	8 Feb 2002 17:38:09 -0000	1.2
  @@ -158,7 +158,7 @@
           getLogger().info( "testNonExistingTableName" );
           
           IdGenerator idGenerator = 
  -            (IdGenerator)m_idGeneratorSelector.select( "ids-size-does-not-exist" );
  +            (IdGenerator)m_idGeneratorSelector.select( "ids-testNonExistingTableName" );
           try
           {
               try
  @@ -181,7 +181,8 @@
       {
           getLogger().info( "testSimpleRequestIdsSize1" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-1"
);
  +        IdGenerator idGenerator = 
  +            (IdGenerator)m_idGeneratorSelector.select( "ids-testSimpleRequestIdsSize1"
);
           try
           {
               int testCount = 100;
  @@ -208,7 +209,8 @@
       {
           getLogger().info( "testSimpleRequestIdsSize10" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-10"
);
  +        IdGenerator idGenerator =
  +            (IdGenerator)m_idGeneratorSelector.select( "ids-testSimpleRequestIdsSize10"
);
           try
           {
               int testCount = 100;
  @@ -235,7 +237,8 @@
       {
           getLogger().info( "testSimpleRequestIdsSize100" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-100"
);
  +        IdGenerator idGenerator =
  +            (IdGenerator)m_idGeneratorSelector.select( "ids-testSimpleRequestIdsSize100"
);
           try
           {
               int testCount = 100;
  @@ -262,28 +265,36 @@
       {
           getLogger().info( "testBigDecimalRequestIdsSize10" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-10-bd"
);
  -        try
  +        if ( isBigDecimalImplemented() )
           {
  -            int testCount = 100;
  -            BigDecimal initial = new BigDecimal( Long.MAX_VALUE + "00" );
  -            
  -            // Initialize the counter in the database.
  -            initializeNextBigDecimalId( "test", initial );
  -            
  -            for ( int i = 0; i < testCount; i++ )
  +            IdGenerator idGenerator =
  +                (IdGenerator)m_idGeneratorSelector.select( "ids-testBigDecimalRequestIdsSize10"
);
  +            try
               {
  -                BigDecimal id = idGenerator.getNextBigDecimalId();
  -                assertEquals( "The returned id was not what was expected.", 
  -                    initial.add( new BigDecimal( i ) ), id );
  +                int testCount = 100;
  +                BigDecimal initial = new BigDecimal( Long.MAX_VALUE + "00" );
  +                
  +                // Initialize the counter in the database.
  +                initializeNextBigDecimalId( "test", initial );
  +                
  +                for ( int i = 0; i < testCount; i++ )
  +                {
  +                    BigDecimal id = idGenerator.getNextBigDecimalId();
  +                    assertEquals( "The returned id was not what was expected.", 
  +                        initial.add( new BigDecimal( i ) ), id );
  +                }
  +                
  +                assertEquals( "The next_id column in the database did not have the expected
value.",
  +                    initial.add( new BigDecimal( testCount ) ), peekNextBigDecimalId( "test"
) );
  +            }
  +            finally
  +            {
  +                m_idGeneratorSelector.release( idGenerator );
               }
  -            
  -            assertEquals( "The next_id column in the database did not have the expected
value.",
  -                initial.add( new BigDecimal( testCount ) ), peekNextBigDecimalId( "test"
) );
           }
  -        finally
  +        else
           {
  -            m_idGeneratorSelector.release( idGenerator );
  +            getLogger().warn( "Test Skipped because BigDecimals are not implemented in
current driver." );
           }
       }
       
  @@ -291,7 +302,7 @@
       {
           getLogger().info( "testMaxByteIds" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-10"
);
  +        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-testMaxByteIds"
);
           try
           {
               int testCount = 100;
  @@ -328,7 +339,7 @@
       {
           getLogger().info( "testMaxShortIds" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-10"
);
  +        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-testMaxShortIds"
);
           try
           {
               int testCount = 100;
  @@ -365,7 +376,7 @@
       {
           getLogger().info( "testMaxIntegerIds" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-10"
);
  +        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-testMaxIntegerIds"
);
           try
           {
               int testCount = 100;
  @@ -402,7 +413,7 @@
       {
           getLogger().info( "testMaxLongIds" );
           
  -        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-size-10"
);
  +        IdGenerator idGenerator = (IdGenerator)m_idGeneratorSelector.select( "ids-testMaxLongIds"
);
           try
           {
               int testCount = 100;
  @@ -438,6 +449,56 @@
       /*---------------------------------------------------------------
        * Utilitity Methods
        *-------------------------------------------------------------*/
  +    /**
  +     * Tests to see whether or not the current DataSource supports BigDecimal
  +     */
  +    private boolean isBigDecimalImplemented()
  +    {
  +        String tableName = "foorbar_table";
  +        
  +        // Add a row that can be selected.
  +        initializeNextLongId( tableName, 1 );
  +        
  +        try
  +        {
  +            Connection conn = m_dataSource.getConnection();
  +            try
  +            {
  +                Statement statement = conn.createStatement();
  +                
  +                ResultSet rs = statement.executeQuery( "SELECT next_id FROM ids " +
  +                    "WHERE table_name = '" + tableName + "'" );
  +                if ( rs.next() )
  +                {
  +                    BigDecimal id = rs.getBigDecimal( 1 );
  +                }
  +                else
  +                {
  +                    fail( tableName + " row not in ids table." );
  +                    return false; // for compiler
  +                }
  +            }
  +            finally
  +            {
  +                conn.close();
  +            }
  +            
  +            // Implemented
  +            return true;
  +        }
  +        catch ( SQLException e )
  +        {
  +            if ( e.toString().indexOf( "NotImplemented" ) > 0 )
  +            {
  +                // Not implemented
  +                return false;
  +            }
  +            getLogger().error( "Unable to peek next_id.", e );
  +            fail( "Unable to peek next_id. " + e );
  +            return false; // for compiler
  +        }
  +    }
  +    
       private void initializeNextBigDecimalId( String tableName, BigDecimal nextId )
       {
           try
  @@ -503,7 +564,7 @@
                   }
                   else
                   {
  -                    fail( "next_id row not in ids table." );
  +                    fail( tableName + " row not in ids table." );
                       return null; // for compiler
                   }
               }
  @@ -537,7 +598,7 @@
                   }
                   else
                   {
  -                    fail( "next_id row not in ids table." );
  +                    fail( tableName + " row not in ids table." );
                       return -1; // for compiler
                   }
               }
  
  
  
  1.2       +29 -7     jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/test/TableIdGeneratorJdbcTestCase.xtest
  
  Index: TableIdGeneratorJdbcTestCase.xtest
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ids/test/TableIdGeneratorJdbcTestCase.xtest,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TableIdGeneratorJdbcTestCase.xtest	8 Feb 2002 12:27:32 -0000	1.1
  +++ TableIdGeneratorJdbcTestCase.xtest	8 Feb 2002 17:38:09 -0000	1.2
  @@ -41,7 +41,7 @@
                   <log-target id-ref="file"/>
               </category>
               
  -            <category name="id-gen" log-level="DEBUG">
  +            <category name="id-gen" log-level="INFO">
                   <log-target id-ref="console"/>
                   <log-target id-ref="file"/>
               </category>
  @@ -87,25 +87,47 @@
           </datasources>
           
           <id-generators>
  -            <table name="ids-size-does-not-exist" block-size="1" table="ids"
  +            <table name="ids-testNonExistingTableName" block-size="1" table="ids"
                      key-table="does-not-exist" logger="id-gen">
                   <dbpool>test-db</dbpool>
               </table>
               
  -            <table name="ids-size-1" block-size="1" table="ids" key-table="test" logger="id-gen">
  +            <table name="ids-testSimpleRequestIdsSize1" block-size="1" table="ids"
  +                   key-table="test" logger="id-gen">
                   <dbpool>test-db</dbpool>
               </table>
               
  -            <table name="ids-size-10" block-size="10" table="ids" key-table="test" logger="id-gen">
  +            <table name="ids-testSimpleRequestIdsSize10" block-size="10" table="ids"
  +                   key-table="test" logger="id-gen">
                   <dbpool>test-db</dbpool>
               </table>
               
  -            <table name="ids-size-100" block-size="100" table="ids" key-table="test"
  -                   logger="id-gen">
  +            <table name="ids-testSimpleRequestIdsSize100" block-size="100" table="ids"
  +                   key-table="test" logger="id-gen">
                   <dbpool>test-db</dbpool>
               </table>
               
  -            <table name="ids-size-10-bd" big-decimals="true" block-size="10" table="ids"
  +            <table name="ids-testBigDecimalRequestIdsSize10" big-decimals="true"
  +                   block-size="10" table="ids" key-table="test" logger="id-gen">
  +                <dbpool>test-db</dbpool>
  +            </table>
  +            
  +            <table name="ids-testMaxByteIds" block-size="10" table="ids"
  +                   key-table="test" logger="id-gen">
  +                <dbpool>test-db</dbpool>
  +            </table>
  +            
  +            <table name="ids-testMaxShortIds" block-size="10" table="ids"
  +                   key-table="test" logger="id-gen">
  +                <dbpool>test-db</dbpool>
  +            </table>
  +            
  +            <table name="ids-testMaxIntegerIds" block-size="10" table="ids"
  +                   key-table="test" logger="id-gen">
  +                <dbpool>test-db</dbpool>
  +            </table>
  +            
  +            <table name="ids-testMaxLongIds" block-size="10" table="ids"
                      key-table="test" logger="id-gen">
                   <dbpool>test-db</dbpool>
               </table>
  
  
  

--
To unsubscribe, e-mail:   <mailto:avalon-cvs-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-cvs-help@jakarta.apache.org>


Mime
View raw message