-
Notifications
You must be signed in to change notification settings - Fork 514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HDDS-9527. Race condition in RocksDatabase #5947
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sumitagrawl , I believe the problem is that there are two atomic variables. Let's remove isClosed
.
- Update
close()
@Override
public void close() {
// wait till all access to rocks db is process to avoid crash while close
while (!counter.compareAndSet(0, Long.MIN_VALUE)) {
try {
Thread.currentThread().sleep(1);
} catch (InterruptedException e) {
close(columnFamilies, db, descriptors, writeOptions, dbOptions);
Thread.currentThread().interrupt();
return;
}
}
// Wait for all background work to be cancelled first. e.g. RDB compaction
db.get().cancelAllBackgroundWork(true);
// Then close all attached listeners
dbOptions.listeners().forEach(listener -> listener.close());
if (columnFamilies != null) {
columnFamilies.values().stream().forEach(f -> f.markClosed());
}
// close when counter is 0, no more operation
close(columnFamilies, db, descriptors, writeOptions, dbOptions);
}
- Change
assertClose()
toacquire()
:
@@ -443,16 +434,17 @@ private boolean shouldClose(RocksDBException e) {
}
}
- private void assertClose() throws IOException {
- if (isClosed()) {
- throw new IOException("Rocks Database is closed");
+ private UncheckedAutoCloseable acquire() throws IOException {
+ if (counter.getAndIncrement() < 0) {
+ counter.getAndDecrement();
+ throw new IOException("Rocks Database is closed: " + this.name);
}
+ return counter::getAndDecrement;
}
- The other methods becomes:
public void put(ColumnFamily family, ByteBuffer key, ByteBuffer value) throws IOException {
try (UncheckedAutoCloseable ignored = acquire()) {
counter.incrementAndGet();
db.get().put(family.getHandle(), writeOptions, key, value);
} catch (RocksDBException e) {
closeOnError(e, true);
throw toIOException(this, "put " + bytes2String(key), e);
}
}
@szetszwo Thanks for review, I have updated using acquire, but still can not remove isClosed variable,
|
You are right. We should check inside the while loop. @Override
public void close() {
// wait till all access to rocks db is process to avoid crash while close
while (!counter.compareAndSet(0, Long.MIN_VALUE)) {
if (counter.get() < 0) {
return;
}
try {
Thread.currentThread().sleep(1);
} catch (InterruptedException e) {
close(columnFamilies, db, descriptors, writeOptions, dbOptions);
Thread.currentThread().interrupt();
return;
}
}
// Wait for all background work to be cancelled first. e.g. RDB compaction
db.get().cancelAllBackgroundWork(true);
// Then close all attached listeners
dbOptions.listeners().forEach(listener -> listener.close());
if (columnFamilies != null) {
columnFamilies.values().stream().forEach(f -> f.markClosed());
}
// close when counter is 0, no more operation
close(columnFamilies, db, descriptors, writeOptions, dbOptions);
}
|
@szetszwo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 the change looks good.
(cherry picked from commit 0c2e2a6)
(cherry picked from commit 0c2e2a6) Change-Id: I58cf584bef32f4a5e104c5bbe5294e5ab9577ff6
What changes were proposed in this pull request?
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-9527
How was this patch tested?