package examples.jdbc.mssqlserver4;

import java.io.*;
import java.sql.*;
import java.util.Properties;

/** This example creates <i>n</i> database connections and runs
 * <i>n</i> threads on each.  You need valid licenses for the number
 * of connections you want to try. The trial version provides 2
 * connections only. Contact support@weblogic.com for more connection
 * licenses.  Your SQL Server must also be configured to accept the
 * number of connections you want to create.
 * <p>
 * The threads run for a designated number of seconds, executing a
 * SQL SELECT statement. You can modify the number of seconds and the
 * SQL command in the code.
 *<h3>To set up this example:</h3>
 *<ol>
 *<li>Set up your development shell as described in <a
 *href=Package-examples.jdbc.mssqlserver4.html>Package examples.jdbc.mssqlserver4</a>.
 *<p>
 *<li> Change the database URL, login, and password connection
 *parameters to correspond to your Microsoft SQL Server
 *configuration.  If you need more help, check
 *the section on connecting to a database in the Developers Guide, <a
 *href=../../../classdocs/API_jmsq4.html>Using
 *WebLogic jDriver for Microsoft SQL Server</a>.
 *
 *<p>
 *
 *<li>Compile this example by executing the following command in your development shell:
 *
 *<p>
 *
 *<font face="Courier New"><b>$ javac -d c:/weblogic/mssqlserver4/classes ThreadsTests.java</b></font>
 *<p>	
 *
 *<li>Run this example by executing the following command in your development shell:
 *
 *<p>
 *
 *<font face="Courier New"><b>$ java examples.jdbc.mssqlserver4.ThreadsTests</b></font>
 *
 *</ol>
 * 
 * @author Copyright (c) 1998-2000 by BEA Systems, Inc. All Rights Reserved. 
 */

public class ThreadsTests
{
  static String driverName = "weblogic.jdbc.mssqlserver4.Driver"; 

  // Change to your own database, host, and port number.
  static String url = "jdbc:weblogic:mssqlserver4";

  // Number of different connections to the server.  When you download
  // the trial software on the net it comes with a single connection
  // license. If you want to run this test you need a multi-connection
  // license.

  static int kNumberOfConnections  = 3;                                      

  // Number of threads sharing the same connection. You can have as
  // many as your computer and database will take.  All the threads
  // use the same connection at the same time. There is no need for
  // them to be synchronized with one another since the driver takes
  // care of synchronization/caching.
  static int kThreadsPerConnection = 4;                             

  // How long should this test last (in seconds)
  static int kTestSeconds = 60;                               

  public static void main(String [] args)
  {
      Properties props = new Properties();
      props.put("user", "sa");
      props.put("password", "secret");
      props.put("server", "pubs@myHost:1433");

      Driver myDriver = null;
      try
      {
        // Load the driver in the Java VM and register with DriverManager
        myDriver = (Driver) Class.forName(driverName).newInstance();

        ReadingThread readers [] = 
          new ReadingThread[kNumberOfConnections * kThreadsPerConnection];

        System.out.println("ThreadsTests - creating " + 
                           (kNumberOfConnections * kThreadsPerConnection) + 
                           " threads using " + kNumberOfConnections + 
                           " connections to the server...\n");

        for (int i = 0 ; i < kNumberOfConnections ; i++)
          {
            //  Connect to the database as administrator (you may need
            //  to type your login/password here) 
            Connection conn = myDriver.connect(url, props);

            // Create a few threads all using the same connection
            for (int j = 0 ; j < kThreadsPerConnection ; j++)
              {
                readers[i * kThreadsPerConnection + j] = new ReadingThread(conn);
              }
          }

        System.out.println("ThreadsTests - " + 
                           (kNumberOfConnections * kThreadsPerConnection) + 
                           " threads were created, starting them...\n");

        // Scan all the threads we launched
        for (int i = 0 ; i < readers.length ; i++)
          {
            if (readers[i] != null) 
              readers[i].start();                      // Start threads
          }

        System.out.println("ThreadsTests - main thread is going to sleep so " +
                           "readers can torture the server...\n");

        Thread.sleep(kTestSeconds * 1000); // Sleep for a while (let
                                  // the threads torture the server)

        System.out.println("ThreadsTests - notifying readers that it's time to quit...\n");

        for(int i = 0 ; i < readers.length ; i++) // Scan all the
                           // threads we launched
          {
            if(readers[i] != null) readers[i].running = false; // Time
              // to quit bothering the server
          }

        for(int i = 0 ; i < readers.length ; i++) // Scan all the
                           // threads we launched
          {
            if(readers[i] != null && readers[i].isAlive()) // If the
                  // i-th thread is still alive
              {
                try { readers[i].join(); } // Wait for this reader to
                                  // die

                catch(InterruptedException ie) { }
              }

            readers[i] = null;
          }

        System.out.println("\nThreadsTests - all readers stopped, we ran " + 
                           totalRuns + " times (read " + totalRows + 
                           " rows total).");
      }

    catch(Exception sqlex) { System.out.println("ThreadsTest - exception " + sqlex); }

    System.out.println("\n\n(press Enter to exit)");

    try { System.in.read(); } // wait for user to press a key before
                                               // closing the console
                                               // window

    catch (IOException e) { return; }
  }

  static int totalRuns = 0; static int totalRows = 0;

  synchronized static void updateStatistics(int runs, int rows)
  {
    totalRuns += runs; 
    totalRows += rows;
  }
}

/** The threads created by ThreadTests execute this class. You can
 * change the SQL the threads execute by changing the argument to
 * statement.executeQuery.
 * 
 * @param connection, the connection the thread uses.
 * @author Copyright (c) 1998-2000 by BEA Systems, Inc. All Rights Reserved.  */
class ReadingThread extends Thread
{
    ReadingThread(Connection connection)
    {
        this.connection = connection;
    }

    Connection connection = null; // Connection used by this thread

    boolean running = true; // True while we're running

    public void run()
    {
        int runs = 0, rows = 0;

        for( ; running ; runs++) // Keep repeating the query
        {
            Statement statement = null;

            try
            {
                // Create a statement that returns some table. You may
                // want to do something different here.
                statement = connection.createStatement(); 

                // You can put any SQL statement you want here...
                ResultSet result = 
                  statement.executeQuery("select * from publishers");

                // Number of columns per row
                int i = 0, columns = result.getMetaData().getColumnCount();     

                // Scan all rows in the result set
                for( ; result.next() && running ; i++)                          
                  {
                    // Scan all columns in the row
                    for(int j = 1 ; j <= columns ; j++)
                    {
                         // Get the value as a string (any type will work this way)
                        String s = result.getString(j);
                        try
                        {
                            Thread.sleep(25);
                        }
                        catch(InterruptedException ie) { }
                    }
                }

                System.out.println(" read " + i + " rows [" + this + "]...");
                ThreadsTests.updateStatistics(1,i); rows += i;
            }

            catch(SQLException sqlEx) 
              { System.out.println(sqlEx); }

            if(statement != null)
            {
                try { statement.close(); } 
                catch (SQLException sqlEx) 
                  { System.out.println(sqlEx); }
            }
        }

        // We can't close the connection because it may be in use by
        // other threads
        connection = null; 
        System.out.println(toString() + " - ran the test " + runs 
                           + " times (total of " + rows + " rows read).");
    }
}

