Skip to content

Commit ee0cd50

Browse files
authored
Reject Range Lock/Unlock Requests with Conflicting Range, User, or Lock Type (#12047)
* fix range lock * make bulkload workload correct * fix bugs and improve test coverage * nits * address comments * nits * address comments
1 parent 432374a commit ee0cd50

13 files changed

+504
-323
lines changed

Diff for: documentation/sphinx/source/rangelock.rst

+8-5
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,19 @@ Ideally, we would use the write lock to achieve this; however, we are currently
3939

4040
How to use?
4141
-----------
42-
Currently, FDB only provides ManagementAPI to lock a range.
43-
Before a user can lock a range, the user must register its identity to the database.
44-
A range can only be locked by a registered owner.
45-
The user can use the following API to register an identity and lock a range.
42+
Currently, FDB provides the ManagementAPI for range locking, intended as an interface for FDB feature development.
43+
Before locking a range, a user must first register their identity with the database.
44+
Only registered users are permitted to acquire range locks.
45+
The following API can be used to register an identity and lock a range.
4646

4747
Put an exclusive read lock on a range. The range must be within the user key space, aka ``"" ~ \xff``.
48+
The locking request is rejected with a range_lock_reject error if the range contains any existing lock with a different range, user, or lock type.
49+
Currently, only the ExclusiveReadLock type is supported, but the design allows for future extension.
4850

4951
``ACTOR Future<Void> takeExclusiveReadLockOnRange(Database cx, KeyRange range, RangeLockOwnerName ownerUniqueID);``
5052

5153
Release an exclusive read lock on a range. The range must be within the user key space, aka ``"" ~ \xff``.
54+
The release request is rejected with a range_lock_reject error if the range contains any existing lock with a different range, user, or lock type.
5255

5356
``ACTOR Future<Void> releaseExclusiveReadLockOnRange(Database cx, KeyRange range, RangeLockOwnerName ownerUniqueID);``
5457

@@ -58,7 +61,7 @@ If the execution is failed, no range is locked/unlocked.
5861

5962
Get exclusive read locks on the input range
6063

61-
``ACTOR Future<std::vector<KeyRange>> getExclusiveReadLockOnRange(Database cx, KeyRange range);``
64+
``ACTOR Future<std::vector<std::pair<KeyRange, RangeLockState>>> findExclusiveReadLockOnRange(Database cx, KeyRange range);``
6265

6366
Register a range lock owner to database metadata.
6467

Diff for: fdbcli/BulkLoadCommand.actor.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,50 @@ ACTOR Future<UID> bulkLoadCommandActor(Database cx, std::vector<StringRef> token
291291
printLongDesc(tokens[0]);
292292
return UID();
293293

294+
} else if (tokencmp(tokens[1], "printlock")) {
295+
// For debugging purposes and invisible to users.
296+
if (tokens.size() != 2) {
297+
fmt::println("{}", BULK_LOAD_STATUS_USAGE);
298+
return UID();
299+
}
300+
std::vector<std::pair<KeyRange, RangeLockState>> lockedRanges =
301+
wait(findExclusiveReadLockOnRange(cx, normalKeys));
302+
fmt::println("Total {} locked ranges", lockedRanges.size());
303+
if (lockedRanges.size() > 10) {
304+
fmt::println("First 10 locks are:");
305+
}
306+
int count = 1;
307+
for (const auto& lock : lockedRanges) {
308+
if (count > 10) {
309+
break;
310+
}
311+
fmt::println("Lock {} on {} for {}", count, lock.first.toString(), lock.second.toString());
312+
count++;
313+
}
314+
return UID();
315+
316+
} else if (tokencmp(tokens[1], "printlockowner")) {
317+
// For debugging purposes and invisible to users.
318+
if (tokens.size() != 2) {
319+
fmt::println("{}", BULK_LOAD_STATUS_USAGE);
320+
return UID();
321+
}
322+
std::vector<RangeLockOwner> owners = wait(getAllRangeLockOwners(cx));
323+
for (const auto owner : owners) {
324+
fmt::println("{}", owner.toString());
325+
}
326+
return UID();
327+
328+
} else if (tokencmp(tokens[1], "clearlock")) {
329+
// For debugging purposes and invisible to users.
330+
if (tokens.size() != 3) {
331+
fmt::println("{}", BULK_LOAD_STATUS_USAGE);
332+
return UID();
333+
}
334+
std::string ownerUniqueID = tokens[2].toString();
335+
wait(releaseExclusiveReadLockByUser(cx, ownerUniqueID));
336+
return UID();
337+
294338
} else {
295339
printUsage(tokens[0]);
296340
printLongDesc(tokens[0]);

0 commit comments

Comments
 (0)