Skip to content

Commit 267a744

Browse files
committed
Use recursion guard
1 parent b1198bc commit 267a744

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

fdb-record-layer-lucene/src/main/java/com/apple/foundationdb/record/lucene/directory/FDBDirectoryLockFactory.java

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ protected static class FDBDirectoryLock extends Lock {
9292
*/
9393
private FDBRecordContext closingContext = null;
9494
private final Object fileLockSetLock = new Object();
95+
private boolean clearingLockNow = false;
9596

9697
private FDBDirectoryLock(final AgilityContext agilityContext, final String lockName, byte[] fileLockKey, int timeWindowMilliseconds) {
9798
this.agilityContext = agilityContext;
@@ -209,45 +210,54 @@ private void fileLockCheckNewLock(byte[] val, long nowMillis) {
209210
}
210211
}
211212

213+
private synchronized boolean inRecursiveClearLock() {
214+
if (clearingLockNow) {
215+
return true;
216+
}
217+
clearingLockNow = true;
218+
return false;
219+
}
220+
212221
private void fileLockClearFlushAndClose(boolean isRecovery) {
213-
synchronized (fileLockSetLock) {
214-
// If called by multiple threads, it seems to be a good idea to block all and allow one of them to do the actual closing.
215-
if (closed) {
216-
return;
217-
}
218-
Function<FDBRecordContext, CompletableFuture<Void>> fileLockFunc = aContext ->
219-
aContext.ensureActive().get(fileLockKey)
220-
.thenAccept(val -> {
222+
if (inRecursiveClearLock()) {
223+
// Here: this function is being called from too many paths. Until cleanup, this guard is here to avoid recursions
224+
return;
225+
}
226+
Function<FDBRecordContext, CompletableFuture<Void>> fileLockFunc = aContext ->
227+
aContext.ensureActive().get(fileLockKey)
228+
.thenAccept(val -> {
229+
synchronized (fileLockSetLock) {
221230
UUID existingUuid = fileLockValueToUuid(val);
222231
if (existingUuid != null && existingUuid.compareTo(selfStampUuid) == 0) {
223232
// clear the lock if locked and matches uuid
224233
aContext.ensureActive().clear(fileLockKey);
225234
closingContext = aContext;
226235
logSelf(isRecovery ? "FileLock: Cleared in Recovery path" : "FileLock: Cleared");
227-
} else if (!isRecovery) {
236+
} else if (! isRecovery) {
228237
throw new AlreadyClosedException("FileLock: Expected to be locked during close.This=" + this + " existingUuid=" + existingUuid); // The string append methods should handle null arguments.
229238
}
230-
});
239+
}
240+
});
231241

232-
if (agilityContext.isClosed()) {
233-
// Here: this is considered to be a recovery path, may bypass closed context.
234-
agilityContext.asyncToSync(LuceneEvents.Waits.WAIT_LUCENE_FILE_LOCK_CLEAR,
235-
agilityContext.applyInRecoveryPath(fileLockFunc));
236-
} else {
237-
// Here: this called during directory close to ensure cleared lock -
238-
agilityContext.asyncToSync(LuceneEvents.Waits.WAIT_LUCENE_FILE_LOCK_CLEAR,
239-
agilityContext.apply(fileLockFunc));
240-
}
241-
agilityContext.recordEvent(LuceneEvents.Events.LUCENE_FILE_LOCK_DURATION, System.nanoTime() - lockStartTime);
242-
boolean flushed = false;
243-
try {
244-
closed = true; // prevent lock stamp update
245-
agilityContext.flush();
246-
flushed = true;
247-
} finally {
248-
closed = flushed; // allow close retry
249-
closingContext = null;
250-
}
242+
if (agilityContext.isClosed()) {
243+
// Here: this is considered to be a recovery path, may bypass closed context.
244+
agilityContext.asyncToSync(LuceneEvents.Waits.WAIT_LUCENE_FILE_LOCK_CLEAR,
245+
agilityContext.applyInRecoveryPath(fileLockFunc));
246+
} else {
247+
// Here: this called during directory close to ensure cleared lock -
248+
agilityContext.asyncToSync(LuceneEvents.Waits.WAIT_LUCENE_FILE_LOCK_CLEAR,
249+
agilityContext.apply(fileLockFunc));
250+
}
251+
agilityContext.recordEvent(LuceneEvents.Events.LUCENE_FILE_LOCK_DURATION, System.nanoTime() - lockStartTime);
252+
boolean flushed = false;
253+
try {
254+
closed = true; // prevent lock stamp update
255+
agilityContext.flush();
256+
flushed = true;
257+
} finally {
258+
closed = flushed; // allow close retry
259+
closingContext = null;
260+
clearingLockNow = false;
251261
}
252262
}
253263

0 commit comments

Comments
 (0)