提交 cb7f7c1b authored 作者: LaughingMan's avatar LaughingMan

Use a Future so exceptions thrown in another thread don't get ignored

上级 3ae7d1e4
...@@ -13,10 +13,12 @@ import java.sql.DriverManager; ...@@ -13,10 +13,12 @@ import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.api.ErrorCode; import java.util.concurrent.ExecutionException;
import org.h2.engine.Constants; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.Tool; import org.h2.util.Tool;
/** /**
...@@ -124,6 +126,47 @@ public class CreateCluster extends Tool { ...@@ -124,6 +126,47 @@ public class CreateCluster extends Tool {
private static void performTransfer(Statement statSource, String urlTarget, private static void performTransfer(Statement statSource, String urlTarget,
String user, String password, String serverList) throws SQLException { String user, String password, String serverList) throws SQLException {
try (PipedReader pipeReader = new PipedReader()) { try (PipedReader pipeReader = new PipedReader()) {
// Delete the target database first.
try (Connection connTarget = DriverManager.getConnection(
urlTarget + ";CLUSTER=''", user, password);
Statement statTarget = connTarget.createStatement())
{
statTarget.execute("DROP ALL OBJECTS DELETE FILES");
}
Future<?> threadFuture = startWriter(pipeReader, statSource);
// Read data from pipe reader, restore on target.
try (Connection connTarget = DriverManager.getConnection(
urlTarget, user, password);
Statement statTarget = connTarget.createStatement())
{
RunScript.execute(connTarget, pipeReader);
// set the cluster to the serverList on both databases
statSource.executeUpdate("SET CLUSTER '" + serverList + "'");
statTarget.executeUpdate("SET CLUSTER '" + serverList + "'");
}
// Check if the writer encountered any exception
try {
threadFuture.get();
} catch (ExecutionException ex) {
throw new SQLException(ex.getCause());
} catch (InterruptedException ex) {
throw new SQLException(ex);
}
} catch (IOException ex) {
throw new SQLException(ex);
}
}
private static Future<?> startWriter(PipedReader pipeReader, Statement statSource)
throws SQLException, IOException {
final ExecutorService thread = Executors.newFixedThreadPool(1);
/* /*
* Pipe writer is used + closed in the inner class, in a * Pipe writer is used + closed in the inner class, in a
* separate thread (needs to be final). It should be initialized * separate thread (needs to be final). It should be initialized
...@@ -139,16 +182,9 @@ public class CreateCluster extends Tool { ...@@ -139,16 +182,9 @@ public class CreateCluster extends Tool {
// Start writing to pipe writer in separate thread. // Start writing to pipe writer in separate thread.
final ResultSet rs = statSource.executeQuery("SCRIPT"); final ResultSet rs = statSource.executeQuery("SCRIPT");
// Delete the target database first. // Since exceptions cannot be thrown across thread boundaries, return
try (Connection connTarget = DriverManager.getConnection( // the task's future so we can check manually
urlTarget + ";CLUSTER=''", user, password); Future<?> threadFuture = thread.submit(new Runnable() {
Statement statTarget = connTarget.createStatement())
{
statTarget.execute("DROP ALL OBJECTS DELETE FILES");
}
new Thread(
new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
...@@ -163,23 +199,11 @@ public class CreateCluster extends Tool { ...@@ -163,23 +199,11 @@ public class CreateCluster extends Tool {
IOUtils.closeSilently(pipeWriter); IOUtils.closeSilently(pipeWriter);
} }
} }
} });
).start();
// Read data from pipe reader, restore on target. thread.shutdown();
try (Connection connTarget = DriverManager.getConnection(
urlTarget, user, password);
Statement statTarget = connTarget.createStatement())
{
RunScript.execute(connTarget, pipeReader);
// set the cluster to the serverList on both databases return threadFuture;
statSource.executeUpdate("SET CLUSTER '" + serverList + "'");
statTarget.executeUpdate("SET CLUSTER '" + serverList + "'");
}
} catch (IOException ex) {
throw new SQLException(ex);
}
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论