Example #1
0
/** @author Bernardo */
public class QueryScheduler implements Runnable {
  private Logger logger = Logger.getLogger(QueryScheduler.class);
  private AtomicInteger queryCounter = new AtomicInteger(0);
  private ConcurrentLinkedQueue<AbstractQueryManager> queue =
      new ConcurrentLinkedQueue<AbstractQueryManager>();
  private AtomicBoolean executingUpdate = new AtomicBoolean();
  private Set<AbstractQueryManager> executingQueries = new HashSet<AbstractQueryManager>();
  private boolean requestShutdown = false;
  private ConnectionManagerImpl connectionManager;
  private LongTransactionQueue longTransactionQueue = new LongTransactionQueue();
  private Thread thread;

  public QueryScheduler(ConnectionManagerImpl connectionManager) {
    this.connectionManager = connectionManager;
    executingUpdate.set(false);
    thread = new Thread(this);
    thread.start();
  }

  public void shutdown() {
    requestShutdown = true;

    try {
      while (thread.isAlive()) {
        synchronized (this) {
          notifyAll();
        }
        thread.join(200);
      }
    } catch (InterruptedException e) {
      System.err.println(e.getMessage());
      e.printStackTrace();
    }
  }

  private int pendingQueries() {
    return executingQueries.size();
  }

  // ** CONCURRENT METHODS **/

  public int getNextQueryNumber() {
    synchronized (queryCounter) {
      int i = queryCounter.intValue();
      queryCounter.set(i + 1);
      return i;
    }
  }

  public void put(AbstractQueryManager s) {
    s.setScheduller(this);

    longTransactionQueue.wait(s);
    synchronized (this) {
      queue.add(s);
      logger.debug(Messages.getString("queryScheduler.added", s.getQueryNumber()));
      notifyAll();
    }
  }

  public synchronized void remove(AbstractQueryManager s) {
    executingQueries.remove(s);
    if (s.getClass().equals(UpdateQueryManager.class)) {
      connectionManager.invalidMetaData();
      executingUpdate.set(false);
    }
    logger.debug(Messages.getString("queryScheduler.remove", s.getQueryNumber()));

    notifyAll();
  }

  private void executeNextInQueue() throws Exception {
    AbstractQueryManager s;

    // Update isolation
    while (executingUpdate.get()) {
      logger.debug(Messages.getString("queryScheduler.waitingForUpdateEnd"));
      wait();
    }
    while ((((AbstractQueryManager) queue.peek()).getClass().equals(UpdateQueryManager.class))
        && (pendingQueries() > 0)) {
      logger.debug(Messages.getString("queryScheduler.waitingForPending"));
      wait();
    }
    s = (AbstractQueryManager) queue.poll();
    executingQueries.add(s);
    if (s.getClass().equals(UpdateQueryManager.class)) executingUpdate.set(true);

    logger.debug(Messages.getString("queryScheduler.dispatching", s.getQueryNumber()));
    s.go();
  }

  public void run() {
    while (!requestShutdown) {
      try {
        logger.debug(Messages.getString("queryScheduler.running"));
        synchronized (this) {
          while (queue.size() != 0) executeNextInQueue();

          logger.debug(Messages.getString("queryScheduler.waitingForMore"));
          wait();
        }
      } catch (Exception e) {
        logger.error(e);
        e.printStackTrace();
      }
    }
  }

  // ******************/

  public ResultSet dump() throws SQLException {
    CachedRowSetImpl rs = new CachedRowSetImpl();
    RowSetMetaDataImpl meta = new RowSetMetaDataImpl();
    meta.setColumnCount(2);
    meta.setColumnName(1, "QUEUE_TYPE");
    meta.setColumnType(1, Types.VARCHAR);
    meta.setColumnName(2, "REQUEST");
    meta.setColumnType(2, Types.VARCHAR);
    rs.setMetaData(meta);

    synchronized (queue) {
      Iterator<AbstractQueryManager> it = queue.iterator();
      while (it.hasNext()) {
        AbstractQueryManager s = (AbstractQueryManager) it.next();
        rs.moveToInsertRow();
        rs.updateString(1, "QUEUE");
        rs.updateString(2, s.getSql());
        rs.insertRow();
        rs.moveToCurrentRow();
      }
      it = executingQueries.iterator();
      while (it.hasNext()) {
        AbstractQueryManager s = (AbstractQueryManager) it.next();
        rs.moveToInsertRow();
        rs.updateString(1, "EXECUTING_QUERIES");
        rs.updateString(2, s.getSql());
        rs.insertRow();
        rs.moveToCurrentRow();
      }
    }
    return rs;
  }

  public int executeUpdate(AbstractQueryManager s) throws RemoteException, SQLException {
    // Isto e thread-safe?
    put(s);
    int count = -1;
    try {
      count = ((UpdateQueryManager) s).executeUpdate();
      logger.debug(Messages.getString("queryScheduler.queryExecuted", s.getQueryNumber()));
    } catch (SQLException e) {
      logger.error(
          Messages.getString(
              "queryScheduler.queryError", new Object[] {s.getQueryNumber(), e.getMessage()}));
      remove(s);
      throw e;
    }
    remove(s);
    return count;
  }

  public ResultSet executeQuery(AbstractQueryManager s) throws RemoteException, SQLException {
    // Isto e thread-safe?
    put(s);
    ResultSet rs = null;
    try {
      rs = ((SelectQueryManager) s).executeQuery();
      logger.debug(Messages.getString("queryScheduler.queryExecuted", s.getQueryNumber()));
    } catch (SQLException e) {
      logger.error(
          Messages.getString(
              "queryScheduler.queryError", new Object[] {s.getQueryNumber(), e.getMessage()}));
      remove(s);
      throw e;
    }
    remove(s);
    return rs;
  }

  public void beginTransaction() {
    longTransactionQueue.block();
  }

  public void endTransaction() {
    longTransactionQueue.unblock();
  }
}
Example #2
0
/** @author Bernardo */
public class UpdateTester extends TestCase {
  HsqlDatabase hsqlDatabase1 = new HsqlDatabase(9001);
  HsqlDatabase hsqlDatabase2 = new HsqlDatabase(9002);
  PargresNodeProcessor nqp1 = new PargresNodeProcessor(3001, 9001);
  PargresNodeProcessor nqp2 = new PargresNodeProcessor(3002, 9002);
  PargresClusterProcessor cqp =
      new PargresClusterProcessor(8050, "./config/PargresConfig2NodesLocal.xml");

  private static Logger logger = Logger.getLogger(UpdateTester.class);

  public void testSimpleQuery() throws Exception {
    Class.forName("org.pargres.jdbc.Driver");
    Connection con = DriverManager.getConnection("jdbc:pargres://localhost", "user", "");
    assertNotNull(con);
    con.createStatement().executeUpdate("UPDATE LINEITEM SET L_QUANTITY = -1 WHERE L_ORDERKEY = 0");
  }

  public void testCreateDropTable() throws Exception {
    Class.forName("org.pargres.jdbc.Driver");
    Connection con = DriverManager.getConnection("jdbc:pargres://localhost", "user", "");
    assertNotNull(con);
    String tableName = "TEST_TABLE";
    con.createStatement().executeUpdate("CREATE TABLE " + tableName + " (ID INTEGER)");
    /*	try {
    	con.createStatement().executeQuery("SELECT * FROM "+tableName);
    } catch (Exception e) {
    	fail("Table not created: "+e);
    }
    */
    con.createStatement().executeUpdate("INSERT INTO " + tableName + " VALUES (1)");
    con.createStatement().executeUpdate("UPDATE " + tableName + " SET ID = 2");
    con.createStatement().executeUpdate("DROP TABLE " + tableName + "");
  }

  public void testConcurrentUpdate() throws Exception {
    Worker w1 = new Worker(JdbcUtil.LAZY_UPDATE);
    Worker w2 = new Worker("SELECT COUNT(*) FROM REGION");
    Worker w3 = new Worker("SELECT COUNT(*) FROM REGION");
    w1.start();
    Thread.sleep(50);
    w2.start();
    Thread.sleep(50);
    w3.start();
    w1.join();
    w2.join();
    w3.join();
    if (w1.endTime == 0) fail("Query w1 failed!");
    if (w2.endTime == 0) fail("Query w2 failed!");
    if (w3.endTime == 0) fail("Query w2 failed!");
    if ((w2.endTime < w1.endTime) || (w3.endTime < w1.endTime))
      fail(
          "Concurrent update processing failed! [w1="
              + w1.endTime
              + "][w2="
              + w2.endTime
              + "][w3="
              + w3.endTime
              + "]");
  }

  public void testTwoUpdates() throws Exception {
    Worker w1 = new Worker(JdbcUtil.LAZY_UPDATE);
    Worker w2 = new Worker(JdbcUtil.LAZY_UPDATE);
    w1.start();
    Thread.sleep(10);
    w2.start();
    w1.join();
    w2.join();
    if (w1.endTime == 0) fail("Query w1 failed!");
    if (w2.endTime == 0) fail("Query w2 failed!");
    if ((w1.endTime >= w2.endTime)) fail("update block failed!");
  }

  public void testManyConcurrentUpdates() throws Exception {
    Worker w1 = new Worker(JdbcUtil.LAZY_UPDATE);
    Worker w2 = new Worker("SELECT COUNT(*) FROM REGION");
    Worker w3 = new Worker("SELECT COUNT(*) FROM REGION");
    Worker w4 = new Worker(JdbcUtil.LAZY_UPDATE);
    Worker w5 = new Worker("SELECT COUNT(*) FROM REGION");
    w1.start();
    Thread.sleep(50);
    w2.start();
    Thread.sleep(50);
    w3.start();
    Thread.sleep(50);
    w4.start();
    Thread.sleep(50);
    w5.start();
    w1.join();
    w2.join();
    w3.join();
    w4.join();
    w5.join();
    if (w1.endTime == 0) fail("Query w1 failed!");
    if (w2.endTime == 0) fail("Query w2 failed!");
    if (w3.endTime == 0) fail("Query w3 failed!");
    if (w4.endTime == 0) fail("Query w4 failed!");
    if (w5.endTime == 0) fail("Query w5 failed!");
    if (w2.endTime < w1.endTime) fail("Concurrent update processing failed!");
    if (w3.endTime < w1.endTime) fail("Concurrent update processing failed!");
    if ((w5.endTime < w4.endTime)) fail("Blocking failed!");
  }
  /*
   * @see TestCase#setUp()
   */
  protected void setUp() throws Exception {
    hsqlDatabase1.start();
    hsqlDatabase2.start();
    nqp1.start();
    nqp2.start();
    cqp.start();
    logger.info("setUp done!");
    // org.pargres.cqp.connection.ConnectionManagerImpl.register();
  }

  /*
   * @see TestCase#tearDown()
   */
  protected void tearDown() throws Exception {
    //	System.out.println("TEAR DOWN!");
    cqp.stop();
    // System.out.println("TEAR DOWN 1!");
    nqp1.stop();
    // System.out.println("TEAR DOWN 2!");
    nqp2.stop();
    // System.out.println("TEAR DOWN 3!");
    hsqlDatabase1.stop();
    // System.out.println("TEAR DOWN 4!");
    hsqlDatabase2.stop();
    // System.out.println("TEAR DOWN 5!");
    // org.pargres.cqp.connection.ConnectionManagerImpl.unregister();
  }

  class Worker extends Thread {
    private String sql;

    public Worker(String sql) {
      this.sql = sql;
    }

    public long endTime = 0;

    public void run() {
      try {
        Class.forName("org.pargres.jdbc.Driver");
        Connection con = DriverManager.getConnection("jdbc:pargres://localhost", "user", "");
        assertNotNull(con);
        boolean e = con.createStatement().execute(sql);
        assertTrue(e);
        endTime = System.currentTimeMillis();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
}