org.eigenbase.test.concurrent
Class ConcurrentTestCommandGenerator

java.lang.Object
  extended by org.eigenbase.test.concurrent.ConcurrentTestCommandGenerator
Direct Known Subclasses:
ConcurrentTestCommandScript, ConcurrentTestTimedCommandGenerator

public class ConcurrentTestCommandGenerator
extends Object

ConcurrentTestCommandGenerator creates instances of ConcurrentTestCommand that perform specific actions in a specific order and within the context of a test thread (ConcurrentTestCommandExecutor).

Typical actions include preparing a SQL statement for execution, executing the statement and verifying its result set, and closing the statement.

A single ConcurrentTestCommandGenerator creates commands for multiple threads. Each thread is represented by an integer "thread ID". Thread IDs may take on any positive integer value and may be a sparse set (e.g. 1, 2, 5).

When each command is created, it is associated with a thread and given an execution order. Execution order values are positive integers, must be unique within a thread, and may be a sparse set.

There are no restrictions on the order of command creation.

Version:
$Id: //open/dev/farrago/src/org/eigenbase/test/concurrent/ConcurrentTestCommandGenerator.java#3 $
Author:
Stephan Zuercher

Nested Class Summary
protected static class ConcurrentTestCommandGenerator.AbstractCommand
          abstract base to handle SQLExceptions
(package private) static class ConcurrentTestCommandGenerator.AutoSynchronizationCommand
          AutoSynchronizationCommand is idential to SynchronizationCommand, except that it is generated automatically by the test harness and is not counted when displaying the step number in which an error occurred.
private static class ConcurrentTestCommandGenerator.CloseCommand
          CloseCommand closes a previously prepared statement.
private static class ConcurrentTestCommandGenerator.CommandWithTimeout
           
private static class ConcurrentTestCommandGenerator.CommitCommand
          CommitCommand commits pending transactions via Connection.commit().
private static class ConcurrentTestCommandGenerator.DdlCommand
          DdlCommand executes DDL commands.
private static class ConcurrentTestCommandGenerator.ExplainCommand
          ExplainCommand executes explain plan commands.
static class ConcurrentTestCommandGenerator.FailedThread
          Describes a thread that failed
private static class ConcurrentTestCommandGenerator.FetchAndCompareCommand
          FetchAndCompareCommand executes a previously prepared statement stored in the ConcurrentTestCommandExecutor and then validates the returned rows against expected data.
private static class ConcurrentTestCommandGenerator.InsertCommand
          InsertCommand exeutes an insert, update or delete SQL statement.
private static class ConcurrentTestCommandGenerator.PrepareCommand
          PrepareCommand creates a PreparedStatement.
private static class ConcurrentTestCommandGenerator.RollbackCommand
          RollbackCommand rolls back pending transactions via Connection.rollback().
private static class ConcurrentTestCommandGenerator.SleepCommand
          SleepCommand causes the execution thread to wait for all other threads in the test before continuing.
(package private) static class ConcurrentTestCommandGenerator.SynchronizationCommand
          SynchronizationCommand causes the execution thread to wait for all other threads in the test before continuing.
 
Field Summary
private static char APOS
           
private static char COMMA
           
protected  boolean debug
           
protected  PrintStream debugStream
           
private  List<ConcurrentTestCommandGenerator.FailedThread> failedThreads
          Collects threads that failed.
protected  Properties jdbcProps
           
protected  String jdbcURL
           
private static char LEFT_BRACKET
           
private static char RIGHT_BRACKET
           
private  TreeMap<Integer,TreeMap<Integer,ConcurrentTestCommand>> threadMap
          Maps Integer thread IDs to a TreeMap.
private  TreeMap<Integer,String> threadNameMap
          Maps Integer thread IDs to thread names.
 
Constructor Summary
ConcurrentTestCommandGenerator()
          Constructs a new ConcurrentTestCommandGenerator.
 
Method Summary
 ConcurrentTestCommand addCloseCommand(int threadId, int order)
          Closes a previously prepared SQL statement.
protected  ConcurrentTestCommand addCommand(int threadId, int order, ConcurrentTestCommand command)
          Handles adding a command to threadMap.
 ConcurrentTestCommand addCommitCommand(int threadId, int order)
          Commits pending transaction on the thread's connection.
 ConcurrentTestCommand addDdlCommand(int threadId, int order, String ddl)
          Executes a DDL statement immediately.
 ConcurrentTestCommand addExplainCommand(int threadId, int order, String sql)
          Adds an "explain plan" command.
 ConcurrentTestCommand addFetchAndCompareCommand(int threadId, int order, int timeout, String expected)
          Executes a previously prepared SQL statement and compares its ResultSet to the given data.
 ConcurrentTestCommand addInsertCommand(int threadId, int order, int timeout, String sql)
          Executes the given SQL via Statement.executeUpdate(String).
 ConcurrentTestCommand addPrepareCommand(int threadId, int order, String sql)
          Creates a PreparedStatement for the given SQL.
 ConcurrentTestCommand addRollbackCommand(int threadId, int order)
          Rolls back pending transaction on the thread's connection.
 ConcurrentTestCommand addSleepCommand(int threadId, int order, long millis)
          Causes the given thread to sleep for the indicated number of milliseconds.
 ConcurrentTestCommand addSynchronizationCommand(int threadId, int order)
          Adds a synchronization commands.
(package private)  void customErrorHandler(ConcurrentTestCommandExecutor executor)
          Custom error handling occurs here if requiresCustomErrorHandling() returns true.
 void execute()
          Creates a ConcurrentTestCommandExecutor object for each define thread, and then runs them all.
 boolean failed()
          Returns whether any test thread failed.
(package private)  Iterator getCommandIterator(Integer threadId)
          Returns an Iterator of ConcurrentTestCommand objects for the given thread ID.
(package private)  Collection getCommands(Integer threadId)
          Returns a Collection of ConcurrentTestCommand objects for the given thread ID.
 List<ConcurrentTestCommandGenerator.FailedThread> getFailedThreads()
           
protected  Set<Integer> getThreadIds()
          Returns a set of thread IDs.
protected  String getThreadName(Integer threadId)
          Retrieves the name of a given thread.
 boolean hasValidSynchronization()
          Validates that all threads have the same number of SynchronizationCommands (otherwise a deadlock is guaranteed).
protected  ConcurrentTestCommandExecutor[] innerExecute()
           
protected  void postExecute(ConcurrentTestCommandExecutor[] threads)
           
(package private)  void printCommands(PrintStream out, Integer threadId)
          Prints a description of the commands to be executed for a given thread.
(package private)  boolean requiresCustomErrorHandling()
          Indicates whether commands generated by this generator require special handling.
 void setDataSource(String jdbcURL, Properties jdbcProps)
          Sets the jdbc data source for executing the command threads.
protected  void setDebug(boolean enabled)
           
protected  void setDebug(boolean enabled, PrintStream alternatePrintStream)
           
 void setThreadName(int threadId, String name)
          Configures a human-readable name for a given thread identifier.
 void synchronizeCommandSets()
          Insures that the number of commands is the same for each thread, fills missing order value with null commands, and interleaves a synchronization command before each actual command.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

APOS

private static final char APOS
See Also:
Constant Field Values

COMMA

private static final char COMMA
See Also:
Constant Field Values

LEFT_BRACKET

private static final char LEFT_BRACKET
See Also:
Constant Field Values

RIGHT_BRACKET

private static final char RIGHT_BRACKET
See Also:
Constant Field Values

debug

protected boolean debug

debugStream

protected PrintStream debugStream

jdbcURL

protected String jdbcURL

jdbcProps

protected Properties jdbcProps

threadMap

private TreeMap<Integer,TreeMap<Integer,ConcurrentTestCommand>> threadMap
Maps Integer thread IDs to a TreeMap. The TreeMap vaules map an Integer execution order to a ConcurrentTestCommand.


threadNameMap

private TreeMap<Integer,String> threadNameMap
Maps Integer thread IDs to thread names.


failedThreads

private List<ConcurrentTestCommandGenerator.FailedThread> failedThreads
Collects threads that failed. Cleared when execution starts, valid whe/n execution has ended. Only failed threads appear in the list, so after a successful test the list is empty.

Constructor Detail

ConcurrentTestCommandGenerator

public ConcurrentTestCommandGenerator()
Constructs a new ConcurrentTestCommandGenerator.

Method Detail

addSynchronizationCommand

public ConcurrentTestCommand addSynchronizationCommand(int threadId,
                                                       int order)
Adds a synchronization commands. When a thread reaches a synchronization command it stops and waits for all other threads to reach their synchronization commands. When all threads have reached their synchronization commands, they are all released simultaneously (or as close as one can get with Object.notifyAll()). Each thread must have exactly the same number of synchronization commands.

Parameters:
threadId - the thread that should execute this command
order - the execution order
Returns:
the newly-added command

addSleepCommand

public ConcurrentTestCommand addSleepCommand(int threadId,
                                             int order,
                                             long millis)
Causes the given thread to sleep for the indicated number of milliseconds. Thread executes Thread.sleep(long).

Parameters:
threadId - the thread that should execute this command
order - the execution order
millis - the length of time to sleep in milliseconds (must not be negative)
Returns:
the newly-added command

addExplainCommand

public ConcurrentTestCommand addExplainCommand(int threadId,
                                               int order,
                                               String sql)
Adds an "explain plan" command.

Parameters:
threadId - the thread that should execute this command
order - the execution order
sql - the explain plan SQL (e.g. "explain plan for select * from t")
Returns:
the newly-added command

addPrepareCommand

public ConcurrentTestCommand addPrepareCommand(int threadId,
                                               int order,
                                               String sql)
Creates a PreparedStatement for the given SQL. This command does not execute the SQL, it merely creates a PreparedStatement and stores it in the ConcurrentTestCommandExecutor.

Parameters:
threadId - the thread that should execute this command
order - the execution order
sql - the SQL to prepare (e.g. "select * from t")
Returns:
the newly-added command
See Also:
addFetchAndCompareCommand(int, int, int, String)

addFetchAndCompareCommand

public ConcurrentTestCommand addFetchAndCompareCommand(int threadId,
                                                       int order,
                                                       int timeout,
                                                       String expected)
Executes a previously prepared SQL statement and compares its ResultSet to the given data.

Expected data format: { 'row1, col1 value', 'row1, col2 value', ... }, { 'row2, col1 value', 'row2, col2 value', ... }, ...

Example: { 'foo', 10, 3.14, null }

Note on timeout: If the previously prepared statement's Statement.setQueryTimeout(int) method throws an UnsupportedOperationException it is ignored and no timeout is set.

Parameters:
threadId - the thread that should execute this command
order - the execution order
timeout - the query timeout, in seconds (see above)
expected - the expected results (see above)
Returns:
the newly-added command

addCloseCommand

public ConcurrentTestCommand addCloseCommand(int threadId,
                                             int order)
Closes a previously prepared SQL statement.

Parameters:
threadId - the thread that should execute this command
order - the execution order
Returns:
the newly-added command

addInsertCommand

public ConcurrentTestCommand addInsertCommand(int threadId,
                                              int order,
                                              int timeout,
                                              String sql)
Executes the given SQL via Statement.executeUpdate(String). May be used for update as well as insert statements.

Note on timeout: If the previously prepared statement's Statement.setQueryTimeout(int) method throws an UnsupportedOperationException it is ignored and no timeout is set.

Parameters:
threadId - the thread that should execute this command
order - the execution order
timeout - the query timeout, in seconds (see above)
sql - the insert/update/delete SQL
Returns:
the newly-added command

addCommitCommand

public ConcurrentTestCommand addCommitCommand(int threadId,
                                              int order)
Commits pending transaction on the thread's connection.

Parameters:
threadId - the thread that should execute this command
order - the execution order
Returns:
the newly-added command

addRollbackCommand

public ConcurrentTestCommand addRollbackCommand(int threadId,
                                                int order)
Rolls back pending transaction on the thread's connection.

Parameters:
threadId - the thread that should execute this command
order - the execution order
Returns:
the newly-added command

addDdlCommand

public ConcurrentTestCommand addDdlCommand(int threadId,
                                           int order,
                                           String ddl)
Executes a DDL statement immediately. Assumes the statement returns no information.

Returns:
the newly-added command

addCommand

protected ConcurrentTestCommand addCommand(int threadId,
                                           int order,
                                           ConcurrentTestCommand command)
Handles adding a command to threadMap.

Returns:
the newly-added command

setThreadName

public void setThreadName(int threadId,
                          String name)
Configures a human-readable name for a given thread identifier. Does not imply that the thread will be created -- that only happens if there are commands added to the thread.


setDebug

protected void setDebug(boolean enabled)

setDebug

protected void setDebug(boolean enabled,
                        PrintStream alternatePrintStream)

setDataSource

public void setDataSource(String jdbcURL,
                          Properties jdbcProps)
Sets the jdbc data source for executing the command threads.


execute

public void execute()
             throws Exception
Creates a ConcurrentTestCommandExecutor object for each define thread, and then runs them all.

Throws:
Exception - if no connection found or if a thread operation is interrupted

innerExecute

protected ConcurrentTestCommandExecutor[] innerExecute()
                                                throws Exception
Throws:
Exception

postExecute

protected void postExecute(ConcurrentTestCommandExecutor[] threads)
                    throws Exception
Throws:
Exception

failed

public boolean failed()
Returns whether any test thread failed. Valid after execute() has returned.


getFailedThreads

public List<ConcurrentTestCommandGenerator.FailedThread> getFailedThreads()
Returns:
the list of failed threads (unmodifiable)

synchronizeCommandSets

public void synchronizeCommandSets()
Insures that the number of commands is the same for each thread, fills missing order value with null commands, and interleaves a synchronization command before each actual command. These steps are required for synchronized execution in FarragoConcurrencyTestCase.


hasValidSynchronization

public boolean hasValidSynchronization()
Validates that all threads have the same number of SynchronizationCommands (otherwise a deadlock is guaranteed).

Returns:
true when valid, false when invalid.

getThreadIds

protected Set<Integer> getThreadIds()
Returns a set of thread IDs.


getThreadName

protected String getThreadName(Integer threadId)
Retrieves the name of a given thread. If no thread names were configured, returns the concatenation of "#" and the thread's numeric identifier.

Returns:
human-readable thread name

requiresCustomErrorHandling

boolean requiresCustomErrorHandling()
Indicates whether commands generated by this generator require special handling. Default implement returns false.


customErrorHandler

void customErrorHandler(ConcurrentTestCommandExecutor executor)
Custom error handling occurs here if requiresCustomErrorHandling() returns true. Default implementation does nothing.


getCommands

Collection getCommands(Integer threadId)
Returns a Collection of ConcurrentTestCommand objects for the given thread ID.


getCommandIterator

Iterator getCommandIterator(Integer threadId)
Returns an Iterator of ConcurrentTestCommand objects for the given thread ID.


printCommands

void printCommands(PrintStream out,
                   Integer threadId)
Prints a description of the commands to be executed for a given thread.