Re: [h2] NullPointerException at concurrent updates (MULTI_THREADED)

2016-12-11 Thread Anatolii K
Thank you sir!

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to h2-database+unsubscr...@googlegroups.com.
To post to this group, send email to h2-database@googlegroups.com.
Visit this group at https://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.


Re: [h2] NullPointerException at concurrent updates (MULTI_THREADED)

2016-12-11 Thread Noel Grandin
thank you for the test case, fix is in master​

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to h2-database+unsubscr...@googlegroups.com.
To post to this group, send email to h2-database@googlegroups.com.
Visit this group at https://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.


[h2] NullPointerException at concurrent updates (MULTI_THREADED)

2016-12-09 Thread Anatolii K
Hi

I've attached test which generates the exception if MULTI_THREADED=1: 

Caused by: java.lang.NullPointerException
at org.h2.mvstore.db.MVPrimaryIndex.getRow(MVPrimaryIndex.java:217)
at org.h2.mvstore.db.MVTable.getRow(MVTable.java:463)
at 
org.h2.mvstore.db.MVSecondaryIndex$MVStoreCursor.get(MVSecondaryIndex.java:489)
at org.h2.index.IndexCursor.get(IndexCursor.java:288)
at org.h2.table.TableFilter.get(TableFilter.java:594)
at org.h2.command.dml.Update.update(Update.java:109)
at org.h2.command.CommandContainer.update(CommandContainer.java:98)
at org.h2.command.Command.executeUpdate(Command.java:258)
... 3 more

at org.h2.engine.SessionRemote.done(SessionRemote.java:624)
at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:191)
at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:201)
at Arte2.call(Bug_H2_1.java:95)
at Arte2.call(Bug_H2_1.java:78)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)


PS. Sorry if it's duplicate topic. I already publish this yesterday but 
can't find it. 

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to h2-database+unsubscr...@googlegroups.com.
To post to this group, send email to h2-database@googlegroups.com.
Visit this group at https://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Bug_H2_1 {

static String dbUrl = "jdbc:h2:tcp://localhost:9002/nioMemFS:db;DB_CLOSE_DELAY=-1;MULTI_THREADED=1";
static String user = "sa", pwd = "";
static int threadCount = 100;

public static void main(String args[]) throws InterruptedException, SQLException {
Arte2[] artes = new Arte2[threadCount];
Connection dbConnect;
try {
Class.forName("org.h2.Driver");
dbConnect = DriverManager.getConnection(dbUrl, user, pwd);
DbPreparator2.prepareScheme(dbConnect);
System.out.println("DB scheme prepared");

DbPreparator2.populate(dbConnect);
System.out.println("DB populated");

for (int i = 0; i < threadCount; i++) {
artes[i] = new Arte2(DriverManager.getConnection(dbUrl, user, pwd));
}
System.out.println("ARTEs created");
} catch (ClassNotFoundException | SQLException e) {
System.out.println("DB Connection Failed: " + dbUrl);
e.printStackTrace();
return;
}

ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
threadPool.submit(artes[i]);
}

while (true) {
Thread.sleep(100);
}
}
}

class DbPreparator2 {

public static final int OBJ_CNT = 1;
private static final String[] SQLs = new String[]{
"CREATE TABLE IF NOT EXISTS "
+ "ACCOUNT (\n"
+ "	ID NUMBER(18,0) not null PRIMARY KEY,\n"
+ "	BALANCE NUMBER null)\n"
};

public static void prepareScheme(Connection db) throws SQLException {
for (String sql : SQLs) {
db.createStatement().execute(sql);
db.commit();
}
}

public static void populate(Connection db) throws SQLException {
PreparedStatement mergeAcctStmt = db.prepareStatement("MERGE INTO Account(id, balance) key (id) VALUES (?, ?)");
for (int i = 0; i < OBJ_CNT; i++) {
mergeAcctStmt.setLong(1, i);
mergeAcctStmt.setBigDecimal(2, BigDecimal.ZERO);
mergeAcctStmt.addBatch();
}
mergeAcctStmt.executeBatch();
db.commit();
}
}

class Arte2 implements Callable {

Connection db;
PreparedStatement updateAcctStmt;

public Arte2(Connection db_) throws SQLException {
db = db_;
db.setAutoCommit(false);
updateAcctStmt = db.prepareStatement("UPDATE account set balance = ? where id = ?");
}

@Override
public Integer call() {
try {
while (true) {
updateAcctStmt.setDouble(1, Math.random());
updateAcctStmt.setLong(2, (int) (Math.random() * DbPreparator2.OBJ_CNT));
updateAcctStmt.execute();
db.commit();
}
} catch (SQLException e) {
System.out.println("DB write error: ");
e.printStackTrace();
System.exit(0);
}
return null;
}
}