提交 20b9c9e9 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Wait for MVStore close completion

上级 143635c9
...@@ -147,6 +147,27 @@ public class MVStore implements AutoCloseable { ...@@ -147,6 +147,27 @@ public class MVStore implements AutoCloseable {
*/ */
private static final int MARKED_FREE = 10_000_000; private static final int MARKED_FREE = 10_000_000;
/**
* Storage is open.
*/
private static final int STATE_OPEN = 0;
/**
* Storage is stopping now. Background writer thread finishes its work
* during this process.
*/
private static final int STATE_STOPPING = 1;
/**
* Storage is closing now.
*/
private static final int STATE_CLOSING = 2;
/**
* Storage is closed.
*/
private static final int STATE_CLOSED = 3;
/** /**
* Lock which governs access to major store operations: store(), close(), ... * Lock which governs access to major store operations: store(), close(), ...
* It should used in a non-reentrant fashion. * It should used in a non-reentrant fashion.
...@@ -162,7 +183,7 @@ public class MVStore implements AutoCloseable { ...@@ -162,7 +183,7 @@ public class MVStore implements AutoCloseable {
private volatile boolean reuseSpace = true; private volatile boolean reuseSpace = true;
private volatile boolean closed; private volatile int state;
private final FileStore fileStore; private final FileStore fileStore;
...@@ -414,7 +435,7 @@ public class MVStore implements AutoCloseable { ...@@ -414,7 +435,7 @@ public class MVStore implements AutoCloseable {
} }
private void panic(IllegalStateException e) { private void panic(IllegalStateException e) {
if (!closed) { if (state == STATE_OPEN) {
handleException(e); handleException(e);
panicException = e; panicException = e;
closeImmediately(); closeImmediately();
...@@ -918,7 +939,7 @@ public class MVStore implements AutoCloseable { ...@@ -918,7 +939,7 @@ public class MVStore implements AutoCloseable {
*/ */
@Override @Override
public void close() { public void close() {
if (closed) { if (isClosed()) {
return; return;
} }
FileStore f = fileStore; FileStore f = fileStore;
...@@ -949,37 +970,42 @@ public class MVStore implements AutoCloseable { ...@@ -949,37 +970,42 @@ public class MVStore implements AutoCloseable {
} }
private void closeStore(boolean shrinkIfPossible) { private void closeStore(boolean shrinkIfPossible) {
if (closed) { if (isClosed()) {
return; return;
} }
stopBackgroundThread(); state = STATE_STOPPING;
closed = true;
storeLock.lock();
try { try {
stopBackgroundThread();
state = STATE_CLOSING;
storeLock.lock();
try { try {
if (fileStore != null && shrinkIfPossible) { try {
shrinkFileIfPossible(0); if (fileStore != null && shrinkIfPossible) {
} shrinkFileIfPossible(0);
// release memory early - this is important when called }
// because of out of memory // release memory early - this is important when called
if (cache != null) { // because of out of memory
cache.clear(); if (cache != null) {
} cache.clear();
if (cacheChunkRef != null) { }
cacheChunkRef.clear(); if (cacheChunkRef != null) {
} cacheChunkRef.clear();
for (MVMap<?, ?> m : new ArrayList<>(maps.values())) { }
m.close(); for (MVMap<?, ?> m : new ArrayList<>(maps.values())) {
m.close();
}
chunks.clear();
maps.clear();
} finally {
if (fileStore != null && !fileStoreIsProvided) {
fileStore.close();
}
} }
chunks.clear();
maps.clear();
} finally { } finally {
if (fileStore != null && !fileStoreIsProvided) { storeLock.unlock();
fileStore.close();
}
} }
} finally { } finally {
storeLock.unlock(); state = STATE_CLOSED;
} }
} }
...@@ -1142,7 +1168,7 @@ public class MVStore implements AutoCloseable { ...@@ -1142,7 +1168,7 @@ public class MVStore implements AutoCloseable {
private void store() { private void store() {
try { try {
if (!closed && hasUnsavedChangesInternal()) { if (isOpenOrStopping() && hasUnsavedChangesInternal()) {
currentStoreVersion = currentVersion; currentStoreVersion = currentVersion;
if (fileStore == null) { if (fileStore == null) {
lastStoredVersion = currentVersion; lastStoredVersion = currentVersion;
...@@ -1719,7 +1745,7 @@ public class MVStore implements AutoCloseable { ...@@ -1719,7 +1745,7 @@ public class MVStore implements AutoCloseable {
if (savedPercent < minPercent) { if (savedPercent < minPercent) {
return; return;
} }
if (!closed) { if (isOpenOrStopping()) {
sync(); sync();
} }
fileStore.truncate(end); fileStore.truncate(end);
...@@ -2392,7 +2418,7 @@ public class MVStore implements AutoCloseable { ...@@ -2392,7 +2418,7 @@ public class MVStore implements AutoCloseable {
* @param map the map * @param map the map
*/ */
void beforeWrite(MVMap<?, ?> map) { void beforeWrite(MVMap<?, ?> map) {
if (saveNeeded && fileStore != null && !closed) { if (saveNeeded && fileStore != null && isOpenOrStopping()) {
saveNeeded = false; saveNeeded = false;
// check again, because it could have been written by now // check again, because it could have been written by now
if (unsavedMemory > autoCommitMemory && autoCommitMemory > 0) { if (unsavedMemory > autoCommitMemory && autoCommitMemory > 0) {
...@@ -2599,7 +2625,7 @@ public class MVStore implements AutoCloseable { ...@@ -2599,7 +2625,7 @@ public class MVStore implements AutoCloseable {
} }
private void checkOpen() { private void checkOpen() {
if (closed) { if (!isOpenOrStopping()) {
throw DataUtils.newIllegalStateException(DataUtils.ERROR_CLOSED, throw DataUtils.newIllegalStateException(DataUtils.ERROR_CLOSED,
"This store is closed", panicException); "This store is closed", panicException);
} }
...@@ -2718,7 +2744,7 @@ public class MVStore implements AutoCloseable { ...@@ -2718,7 +2744,7 @@ public class MVStore implements AutoCloseable {
*/ */
void writeInBackground() { void writeInBackground() {
try { try {
if (closed) { if (!isOpenOrStopping()) {
return; return;
} }
...@@ -2780,7 +2806,23 @@ public class MVStore implements AutoCloseable { ...@@ -2780,7 +2806,23 @@ public class MVStore implements AutoCloseable {
} }
public boolean isClosed() { public boolean isClosed() {
return closed; if (state == STATE_OPEN) {
return false;
}
int millis = 1;
while (state != STATE_CLOSED) {
try {
Thread.sleep(millis++);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
return true;
}
private boolean isOpenOrStopping() {
return state <= STATE_STOPPING;
} }
private void stopBackgroundThread() { private void stopBackgroundThread() {
...@@ -2825,7 +2867,7 @@ public class MVStore implements AutoCloseable { ...@@ -2825,7 +2867,7 @@ public class MVStore implements AutoCloseable {
} }
stopBackgroundThread(); stopBackgroundThread();
// start the background thread if needed // start the background thread if needed
if (millis > 0) { if (millis > 0 && state == STATE_OPEN) {
int sleep = Math.max(1, millis / 10); int sleep = Math.max(1, millis / 10);
BackgroundWriterThread t = BackgroundWriterThread t =
new BackgroundWriterThread(this, sleep, new BackgroundWriterThread(this, sleep,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论