/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.synth; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.h2.test.utils.SelfDestructor; /** * The application code for the {@link TestHalt} application. */ public class TestHaltApp extends TestHalt { private int rowCount; /** * This method is called when executing this application from the command * line. * * @param args the command line parameters */ public static void main(String... args) throws Exception { SelfDestructor.startCountdown(60); TestHaltApp app = new TestHaltApp(); if (args.length == 0) { app.controllerTest(); } else { app.operations = Integer.parseInt(args[0]); app.flags = Integer.parseInt(args[1]); app.value = Integer.parseInt(args[2]); app.processRunRandom(); } } private void execute(Statement stat, String sql) throws SQLException { traceOperation("execute: " + sql); stat.execute(sql); } /** * Initialize the database. */ protected void controllerInit() throws SQLException { Statement stat = conn.createStatement(); // stat.execute("CREATE TABLE TEST(ID IDENTITY, NAME VARCHAR(255))"); for (int i = 0; i < 20; i++) { execute(stat, "DROP TABLE IF EXISTS TEST" + i); execute(stat, "CREATE TABLE TEST" + i + "(ID INT PRIMARY KEY, NAME VARCHAR(255))"); } for (int i = 0; i < 20; i += 2) { execute(stat, "DROP TABLE TEST" + i); } execute(stat, "DROP TABLE IF EXISTS TEST"); execute(stat, "CREATE TABLE TEST(ID BIGINT GENERATED BY DEFAULT AS IDENTITY, NAME VARCHAR(255), DATA CLOB)"); } /** * Wait after the application has been started. */ protected void controllerWaitAfterAppStart() throws Exception { int sleep = 10 + random.nextInt(300); if ((flags & FLAG_NO_DELAY) == 0) { sleep += 1000; } Thread.sleep(sleep); } /** * This method is called after a simulated crash. The method should check if * the data is transactionally consistent and throw an exception if not. * * @throws SQLException if the data is not consistent. */ protected void controllerCheckAfterCrash() throws SQLException { Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("SELECT COUNT(*) FROM TEST"); rs.next(); int count = rs.getInt(1); System.out.println("count: " + count); if (count % 2 != 0) { traceOperation("row count: " + count); throw new SQLException("Unexpected odd row count: " + count); } } /** * Initialize the application. */ protected void processAppStart() throws SQLException { Statement stat = conn.createStatement(); if ((flags & FLAG_NO_DELAY) != 0) { execute(stat, "SET WRITE_DELAY 0"); execute(stat, "SET MAX_LOG_SIZE 1"); } ResultSet rs = stat.executeQuery("SELECT COUNT(*) FROM TEST"); rs.next(); rowCount = rs.getInt(1); traceOperation("rows: " + rowCount, null); } /** * Run the application code. */ protected void processAppRun() throws SQLException { conn.setAutoCommit(false); traceOperation("setAutoCommit false"); int rows = 10000 + value; PreparedStatement prepInsert = conn.prepareStatement("INSERT INTO TEST(NAME, DATA) VALUES('Hello World', ?)"); PreparedStatement prepUpdate = conn .prepareStatement("UPDATE TEST SET NAME = 'Hallo Welt', DATA = ? WHERE ID = ?"); for (int i = 0; i < rows; i++) { Statement stat = conn.createStatement(); if ((operations & OP_INSERT) != 0) { if ((flags & FLAG_LOBS) != 0) { String s = getRandomString(random.nextInt(200)); prepInsert.setString(1, s); traceOperation("insert " + s); prepInsert.execute(); } else { execute(stat, "INSERT INTO TEST(NAME) VALUES('Hello World')"); } ResultSet rs = stat.getGeneratedKeys(); rs.next(); int key = rs.getInt(1); traceOperation("inserted key: " + key); rowCount++; } if ((operations & OP_UPDATE) != 0) { if ((flags & FLAG_LOBS) != 0) { String s = getRandomString(random.nextInt(200)); prepUpdate.setString(1, s); int x = random.nextInt(rowCount + 1); prepUpdate.setInt(2, x); traceOperation("update " + s + " " + x); prepUpdate.execute(); } else { int x = random.nextInt(rowCount + 1); execute(stat, "UPDATE TEST SET VALUE = 'Hallo Welt' WHERE ID = " + x); } } if ((operations & OP_DELETE) != 0) { int x = random.nextInt(rowCount + 1); traceOperation("deleting " + x); int uc = stat.executeUpdate("DELETE FROM TEST WHERE ID = " + x); traceOperation("updated: " + uc); rowCount -= uc; } traceOperation("rowCount " + rowCount); traceOperation("rows now: " + rowCount, null); if (rowCount % 2 == 0) { traceOperation("commit " + rowCount); conn.commit(); traceOperation("committed: " + rowCount, null); } if ((flags & FLAG_NO_DELAY) != 0) { if (random.nextInt(10) == 0 && (rowCount % 2 == 0)) { execute(stat, "CHECKPOINT"); } } } traceOperation("rollback"); conn.rollback(); } }