提交 691e8a55 authored 作者: Andrei Tokar's avatar Andrei Tokar

protect first background exception encountered and relate it to clients

上级 ff4993e4
......@@ -218,7 +218,7 @@ public class Database implements DataHandler {
private MVTableEngine.Store mvStore;
private int retentionTime;
private boolean allowBuiltinAliasOverride;
private DbException backgroundException;
private final AtomicReference<DbException> backgroundException = new AtomicReference<>();
private JavaObjectSerializer javaObjectSerializer;
private String javaObjectSerializerName;
private volatile boolean javaObjectSerializerInitialized;
......@@ -314,6 +314,7 @@ public class Database implements DataHandler {
OnExitDatabaseCloser.register(this);
}
} catch (Throwable e) {
try {
if (e instanceof OutOfMemoryError) {
e.fillInStackTrace();
}
......@@ -331,6 +332,9 @@ public class Database implements DataHandler {
traceSystem.close();
}
closeOpenFilesAndUnlock(false);
} catch(Throwable ex) {
e.addSuppressed(ex);
}
throw DbException.convert(e);
}
}
......@@ -675,8 +679,7 @@ public class Database implements DataHandler {
if (readOnly ||
fileLockMethod == FileLockMethod.NO ||
fileLockMethod == FileLockMethod.SERIALIZED ||
fileLockMethod == FileLockMethod.FS ||
!persistent) {
fileLockMethod == FileLockMethod.FS) {
throw DbException.getUnsupportedException(
"autoServerMode && (readOnly || " +
"fileLockMethod == NO || " +
......@@ -2116,22 +2119,15 @@ public class Database implements DataHandler {
}
private void throwLastBackgroundException() {
if (backgroundException != null) {
// we don't care too much about concurrency here,
// we just want to make sure the exception is _normally_
// not just logged to the .trace.db file
DbException b = backgroundException;
backgroundException = null;
DbException b = backgroundException.getAndSet(null);
if (b != null) {
// wrap the exception, so we see it was thrown here
throw DbException.get(b.getErrorCode(), b, b.getMessage());
}
}
}
public void setBackgroundException(DbException e) {
if (backgroundException == null) {
backgroundException = e;
if (backgroundException.compareAndSet(null, e)) {
TraceSystem t = getTraceSystem();
if (t != null) {
t.getTrace(Trace.DATABASE).error(e, "flush");
......@@ -2139,6 +2135,15 @@ public class Database implements DataHandler {
}
}
public Throwable getBackgroundException() {
IllegalStateException exception = mvStore.getStore().getPanicException();
if(exception != null) {
return exception;
}
return backgroundException.getAndSet(null);
}
/**
* Flush all pending changes to the transaction log.
*/
......@@ -2153,7 +2158,7 @@ public class Database implements DataHandler {
try {
mvStore.flush();
} catch (RuntimeException e) {
backgroundException = DbException.convert(e);
backgroundException.compareAndSet(null, DbException.convert(e));
throw e;
}
}
......
......@@ -1676,8 +1676,9 @@ public class Session extends SessionWithState implements TransactionStore.Rollba
MVTableEngine.Store store = database.getMvStore();
if (store != null) {
if (store.getStore().isClosed()) {
Throwable backgroundException = database.getBackgroundException();
database.shutdownImmediately();
throw DbException.get(ErrorCode.DATABASE_IS_CLOSED);
throw DbException.get(ErrorCode.DATABASE_IS_CLOSED, backgroundException);
}
transaction = store.getTransactionStore().begin(this, this.lockTimeout, id);
}
......
......@@ -292,7 +292,7 @@ public class MVStore {
private final Object compactSync = new Object();
private IllegalStateException panicException;
private volatile IllegalStateException panicException;
private long lastTimeAbsolute;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论