import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class Increment
{
	public static void main(String args[])
	{
		try {
			Class.forName("org.postgresql.Driver");
		} catch (Exception e) { System.out.println("Couldn't load JDBC driver"); }
		Connection conn = null;
		try {
			  // database is called 'rob'.  server is on neelix.
			conn = DriverManager.getConnection("jdbc:postgresql://neelix/rob", "greenrj", "");
		} catch (SQLException e) {
			 // handle any errors
			System.out.println("SQLException: " + e.getMessage());
			System.out.println("SQLState: " + e.getSQLState());
			System.out.println("VendorError: " + e.getErrorCode());
		}

		if (conn == null) {
			System.out.println("Couldn't connect to database");
			return;
		}
		else {
			try {
				conn.setAutoCommit(false);
				conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
			} catch (SQLException e) { }

			for (int i=0; i<30; ++i) {
				System.out.println();
				for (int j=0; j<3; ++j) {
					boolean retry = false;
					do {
						retry = false;
						Statement stmt = null;
						ResultSet rs = null;
						try {
							stmt = conn.createStatement();
							rs = stmt.executeQuery("SELECT value FROM Values WHERE valueId = " + Integer.toString(j));
							if (rs != null && rs.first()) {
								int v = rs.getInt(1);
								System.out.println("i="+ i+ ", j="+ j+ ", v=" + v);  // do some I/O
								++v;
								stmt.executeUpdate("UPDATE Values SET value = " + Integer.toString(v) + "WHERE valueId = " + Integer.toString(j));
								conn.commit();
							}
						} catch (SQLException e) {
							 // handle any errors
							System.out.print("SQLException: " + e.getMessage());
							System.out.println("SQLState: " + e.getSQLState());
//							System.out.println("VendorError: " + e.getErrorCode());
							if (e.getSQLState() == null || e.getSQLState().equals("40001")) {
								try {
									conn.rollback();
									retry = true;
								} catch (SQLException se) {
									System.out.println("Failed while rolling back after exception");
									System.out.println("SQLException: " + se.getMessage());
									System.out.println("SQLState: " + se.getSQLState());
								}
							}
						} finally {
							try {
								if (stmt != null) { 
									stmt.close(); 
									stmt = null; 
								}

								if (rs != null) { 
									rs.close(); 
									rs = null; 
								}
							} catch (SQLException sqlEx) {
								System.out.println("* Failed to close statement/resultset");
							} // ignore 
						} 
					} while (retry);
				}
			}
			try {
				conn.close();
				System.out.println("closing connection");
			} catch (SQLException sqlEx) { } // ignore 
		}
	}
}
