Skip to content

Commit 87d9f36

Browse files
HDDS-2244. Use new ReadWrite lock in OzoneManager. (#1589)
1 parent 72ae371 commit 87d9f36

28 files changed

+232
-123
lines changed

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/lock/OzoneManagerLock.java

Lines changed: 102 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.util.ArrayList;
2323
import java.util.List;
24+
import java.util.function.Consumer;
2425

2526
import org.slf4j.Logger;
2627
import org.slf4j.LoggerFactory;
@@ -75,6 +76,9 @@ public class OzoneManagerLock {
7576
private static final Logger LOG =
7677
LoggerFactory.getLogger(OzoneManagerLock.class);
7778

79+
private static final String READ_LOCK = "read";
80+
private static final String WRITE_LOCK = "write";
81+
7882
private final LockManager<String> manager;
7983
private final ThreadLocal<Short> lockSet = ThreadLocal.withInitial(
8084
() -> Short.valueOf((short)0));
@@ -105,15 +109,66 @@ public OzoneManagerLock(Configuration conf) {
105109
* should be bucket name. For remaining all resource only one param should
106110
* be passed.
107111
*/
112+
@Deprecated
108113
public boolean acquireLock(Resource resource, String... resources) {
109114
String resourceName = generateResourceName(resource, resources);
115+
return lock(resource, resourceName, manager::writeLock, WRITE_LOCK);
116+
}
117+
118+
/**
119+
* Acquire read lock on resource.
120+
*
121+
* For S3_BUCKET_LOCK, VOLUME_LOCK, BUCKET_LOCK type resource, same
122+
* thread acquiring lock again is allowed.
123+
*
124+
* For USER_LOCK, PREFIX_LOCK, S3_SECRET_LOCK type resource, same thread
125+
* acquiring lock again is not allowed.
126+
*
127+
* Special Note for USER_LOCK: Single thread can acquire single user lock/
128+
* multi user lock. But not both at the same time.
129+
* @param resource - Type of the resource.
130+
* @param resources - Resource names on which user want to acquire lock.
131+
* For Resource type BUCKET_LOCK, first param should be volume, second param
132+
* should be bucket name. For remaining all resource only one param should
133+
* be passed.
134+
*/
135+
public boolean acquireReadLock(Resource resource, String... resources) {
136+
String resourceName = generateResourceName(resource, resources);
137+
return lock(resource, resourceName, manager::readLock, READ_LOCK);
138+
}
139+
140+
141+
/**
142+
* Acquire write lock on resource.
143+
*
144+
* For S3_BUCKET_LOCK, VOLUME_LOCK, BUCKET_LOCK type resource, same
145+
* thread acquiring lock again is allowed.
146+
*
147+
* For USER_LOCK, PREFIX_LOCK, S3_SECRET_LOCK type resource, same thread
148+
* acquiring lock again is not allowed.
149+
*
150+
* Special Note for USER_LOCK: Single thread can acquire single user lock/
151+
* multi user lock. But not both at the same time.
152+
* @param resource - Type of the resource.
153+
* @param resources - Resource names on which user want to acquire lock.
154+
* For Resource type BUCKET_LOCK, first param should be volume, second param
155+
* should be bucket name. For remaining all resource only one param should
156+
* be passed.
157+
*/
158+
public boolean acquireWriteLock(Resource resource, String... resources) {
159+
String resourceName = generateResourceName(resource, resources);
160+
return lock(resource, resourceName, manager::writeLock, WRITE_LOCK);
161+
}
162+
163+
private boolean lock(Resource resource, String resourceName,
164+
Consumer<String> lockFn, String lockType) {
110165
if (!resource.canLock(lockSet.get())) {
111166
String errorMessage = getErrorMessage(resource);
112167
LOG.error(errorMessage);
113168
throw new RuntimeException(errorMessage);
114169
} else {
115-
manager.lock(resourceName);
116-
LOG.debug("Acquired {} lock on resource {}", resource.name,
170+
lockFn.accept(resourceName);
171+
LOG.debug("Acquired {} {} lock on resource {}", lockType, resource.name,
117172
resourceName);
118173
lockSet.set(resource.setLock(lockSet.get()));
119174
return true;
@@ -197,19 +252,19 @@ public boolean acquireMultiUserLock(String firstUser, String secondUser) {
197252

198253
if (compare == 0) {
199254
// both users are equal.
200-
manager.lock(firstUser);
255+
manager.writeLock(firstUser);
201256
} else {
202-
manager.lock(firstUser);
257+
manager.writeLock(firstUser);
203258
try {
204-
manager.lock(secondUser);
259+
manager.writeLock(secondUser);
205260
} catch (Exception ex) {
206261
// We got an exception acquiring 2nd user lock. Release already
207262
// acquired user lock, and throw exception to the user.
208-
manager.unlock(firstUser);
263+
manager.writeUnlock(firstUser);
209264
throw ex;
210265
}
211266
}
212-
LOG.debug("Acquired {} lock on resource {} and {}", resource.name,
267+
LOG.debug("Acquired Write {} lock on resource {} and {}", resource.name,
213268
firstUser, secondUser);
214269
lockSet.set(resource.setLock(lockSet.get()));
215270
return true;
@@ -240,35 +295,66 @@ public void releaseMultiUserLock(String firstUser, String secondUser) {
240295

241296
if (compare == 0) {
242297
// both users are equal.
243-
manager.unlock(firstUser);
298+
manager.writeUnlock(firstUser);
244299
} else {
245-
manager.unlock(firstUser);
246-
manager.unlock(secondUser);
300+
manager.writeUnlock(firstUser);
301+
manager.writeUnlock(secondUser);
247302
}
248-
LOG.debug("Release {} lock on resource {} and {}", resource.name,
303+
LOG.debug("Release Write {} lock on resource {} and {}", resource.name,
249304
firstUser, secondUser);
250305
lockSet.set(resource.clearLock(lockSet.get()));
251306
}
252307

253308
/**
254-
* Release lock on resource.
309+
* Release write lock on resource.
310+
* @param resource - Type of the resource.
311+
* @param resources - Resource names on which user want to acquire lock.
312+
* For Resource type BUCKET_LOCK, first param should be volume, second param
313+
* should be bucket name. For remaining all resource only one param should
314+
* be passed.
315+
*/
316+
public void releaseWriteLock(Resource resource, String... resources) {
317+
String resourceName = generateResourceName(resource, resources);
318+
unlock(resource, resourceName, manager::writeUnlock, WRITE_LOCK);
319+
}
320+
321+
/**
322+
* Release read lock on resource.
323+
* @param resource - Type of the resource.
324+
* @param resources - Resource names on which user want to acquire lock.
325+
* For Resource type BUCKET_LOCK, first param should be volume, second param
326+
* should be bucket name. For remaining all resource only one param should
327+
* be passed.
328+
*/
329+
public void releaseReadLock(Resource resource, String... resources) {
330+
String resourceName = generateResourceName(resource, resources);
331+
unlock(resource, resourceName, manager::readUnlock, READ_LOCK);
332+
}
333+
334+
/**
335+
* Release write lock on resource.
255336
* @param resource - Type of the resource.
256337
* @param resources - Resource names on which user want to acquire lock.
257338
* For Resource type BUCKET_LOCK, first param should be volume, second param
258339
* should be bucket name. For remaining all resource only one param should
259340
* be passed.
260341
*/
342+
@Deprecated
261343
public void releaseLock(Resource resource, String... resources) {
262344
String resourceName = generateResourceName(resource, resources);
345+
unlock(resource, resourceName, manager::writeUnlock, WRITE_LOCK);
346+
}
347+
348+
private void unlock(Resource resource, String resourceName,
349+
Consumer<String> lockFn, String lockType) {
263350
// TODO: Not checking release of higher order level lock happened while
264351
// releasing lower order level lock, as for that we need counter for
265352
// locks, as some locks support acquiring lock again.
266-
manager.unlock(resourceName);
353+
lockFn.accept(resourceName);
267354
// clear lock
268-
LOG.debug("Release {}, lock on resource {}", resource.name,
269-
resource.name, resourceName);
355+
LOG.debug("Release {} {}, lock on resource {}", lockType, resource.name,
356+
resourceName);
270357
lockSet.set(resource.clearLock(lockSet.get()));
271-
272358
}
273359

274360
/**

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/BucketManagerImpl.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ public OmBucketInfo getBucketInfo(String volumeName, String bucketName)
219219
throws IOException {
220220
Preconditions.checkNotNull(volumeName);
221221
Preconditions.checkNotNull(bucketName);
222-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
222+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
223+
bucketName);
223224
try {
224225
String bucketKey = metadataManager.getBucketKey(volumeName, bucketName);
225226
OmBucketInfo value = metadataManager.getBucketTable().get(bucketKey);
@@ -237,7 +238,7 @@ public OmBucketInfo getBucketInfo(String volumeName, String bucketName)
237238
}
238239
throw ex;
239240
} finally {
240-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
241+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
241242
bucketName);
242243
}
243244
}
@@ -520,7 +521,7 @@ public List<OzoneAcl> getAcl(OzoneObj obj) throws IOException {
520521
}
521522
String volume = obj.getVolumeName();
522523
String bucket = obj.getBucketName();
523-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volume, bucket);
524+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
524525
try {
525526
String dbBucketKey = metadataManager.getBucketKey(volume, bucket);
526527
OmBucketInfo bucketInfo =
@@ -538,7 +539,7 @@ public List<OzoneAcl> getAcl(OzoneObj obj) throws IOException {
538539
}
539540
throw ex;
540541
} finally {
541-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volume, bucket);
542+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volume, bucket);
542543
}
543544
}
544545

@@ -557,7 +558,7 @@ public boolean checkAccess(OzoneObj ozObject, RequestContext context)
557558

558559
String volume = ozObject.getVolumeName();
559560
String bucket = ozObject.getBucketName();
560-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volume, bucket);
561+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
561562
try {
562563
String dbBucketKey = metadataManager.getBucketKey(volume, bucket);
563564
OmBucketInfo bucketInfo =
@@ -581,7 +582,7 @@ public boolean checkAccess(OzoneObj ozObject, RequestContext context)
581582
throw new OMException("Check access operation failed for " +
582583
"bucket:" + bucket, ex, INTERNAL_ERROR);
583584
} finally {
584-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volume, bucket);
585+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volume, bucket);
585586
}
586587
}
587588
}

hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/KeyManagerImpl.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ public OmKeyInfo lookupKey(OmKeyArgs args, String clientAddress)
622622
String volumeName = args.getVolumeName();
623623
String bucketName = args.getBucketName();
624624
String keyName = args.getKeyName();
625-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
625+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
626+
bucketName);
626627
try {
627628
String keyBytes = metadataManager.getOzoneKey(
628629
volumeName, bucketName, keyName);
@@ -682,7 +683,7 @@ public OmKeyInfo lookupKey(OmKeyArgs args, String clientAddress)
682683
throw new OMException(ex.getMessage(),
683684
KEY_NOT_FOUND);
684685
} finally {
685-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
686+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
686687
bucketName);
687688
}
688689
}
@@ -1311,7 +1312,8 @@ public OmMultipartUploadList listMultipartUploads(String volumeName,
13111312
Preconditions.checkNotNull(volumeName);
13121313
Preconditions.checkNotNull(bucketName);
13131314

1314-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
1315+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
1316+
bucketName);
13151317
try {
13161318

13171319
List<String> multipartUploadKeys =
@@ -1354,7 +1356,7 @@ public OmMultipartUploadList listMultipartUploads(String volumeName,
13541356
throw new OMException(ex.getMessage(), ResultCodes
13551357
.LIST_MULTIPART_UPLOAD_PARTS_FAILED);
13561358
} finally {
1357-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
1359+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
13581360
bucketName);
13591361
}
13601362
}
@@ -1370,7 +1372,8 @@ public OmMultipartUploadListParts listParts(String volumeName,
13701372
boolean isTruncated = false;
13711373
int nextPartNumberMarker = 0;
13721374

1373-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
1375+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
1376+
bucketName);
13741377
try {
13751378
String multipartKey = metadataManager.getMultipartKey(volumeName,
13761379
bucketName, keyName, uploadID);
@@ -1457,7 +1460,7 @@ public OmMultipartUploadListParts listParts(String volumeName,
14571460
throw new OMException(ex.getMessage(), ResultCodes
14581461
.LIST_MULTIPART_UPLOAD_PARTS_FAILED);
14591462
} finally {
1460-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
1463+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
14611464
bucketName);
14621465
}
14631466
}
@@ -1603,7 +1606,7 @@ public List<OzoneAcl> getAcl(OzoneObj obj) throws IOException {
16031606
String bucket = obj.getBucketName();
16041607
String keyName = obj.getKeyName();
16051608

1606-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volume, bucket);
1609+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
16071610
try {
16081611
validateBucket(volume, bucket);
16091612
String objectKey = metadataManager.getOzoneKey(volume, bucket, keyName);
@@ -1620,7 +1623,7 @@ public List<OzoneAcl> getAcl(OzoneObj obj) throws IOException {
16201623
}
16211624
throw ex;
16221625
} finally {
1623-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volume, bucket);
1626+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volume, bucket);
16241627
}
16251628
}
16261629

@@ -1648,7 +1651,7 @@ public boolean checkAccess(OzoneObj ozObject, RequestContext context)
16481651
.setKeyName(keyName)
16491652
.build();
16501653

1651-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volume, bucket);
1654+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volume, bucket);
16521655
try {
16531656
validateBucket(volume, bucket);
16541657
OmKeyInfo keyInfo = null;
@@ -1687,7 +1690,7 @@ public boolean checkAccess(OzoneObj ozObject, RequestContext context)
16871690
throw new OMException("Check access operation failed for " +
16881691
"key:" + keyName, ex, INTERNAL_ERROR);
16891692
} finally {
1690-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volume, bucket);
1693+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volume, bucket);
16911694
}
16921695
}
16931696

@@ -1732,7 +1735,8 @@ public OzoneFileStatus getFileStatus(OmKeyArgs args) throws IOException {
17321735
String bucketName = args.getBucketName();
17331736
String keyName = args.getKeyName();
17341737

1735-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
1738+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
1739+
bucketName);
17361740
try {
17371741
// Check if this is the root of the filesystem.
17381742
if (keyName.length() == 0) {
@@ -1770,7 +1774,7 @@ public OzoneFileStatus getFileStatus(OmKeyArgs args) throws IOException {
17701774
volumeName + " bucket: " + bucketName + " key: " + keyName,
17711775
FILE_NOT_FOUND);
17721776
} finally {
1773-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
1777+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
17741778
bucketName);
17751779
}
17761780
}
@@ -1915,7 +1919,8 @@ public OmKeyInfo lookupFile(OmKeyArgs args, String clientAddress)
19151919
String bucketName = args.getBucketName();
19161920
String keyName = args.getKeyName();
19171921

1918-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
1922+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
1923+
bucketName);
19191924
try {
19201925
OzoneFileStatus fileStatus = getFileStatus(args);
19211926
if (fileStatus.isFile()) {
@@ -1926,7 +1931,7 @@ public OmKeyInfo lookupFile(OmKeyArgs args, String clientAddress)
19261931
}
19271932
//if key is not of type file or if key is not found we throw an exception
19281933
} finally {
1929-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
1934+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
19301935
bucketName);
19311936
}
19321937

@@ -1953,7 +1958,8 @@ public List<OzoneFileStatus> listStatus(OmKeyArgs args, boolean recursive,
19531958
String keyName = args.getKeyName();
19541959

19551960
List<OzoneFileStatus> fileStatusList = new ArrayList<>();
1956-
metadataManager.getLock().acquireLock(BUCKET_LOCK, volumeName, bucketName);
1961+
metadataManager.getLock().acquireReadLock(BUCKET_LOCK, volumeName,
1962+
bucketName);
19571963
try {
19581964
if (Strings.isNullOrEmpty(startKey)) {
19591965
OzoneFileStatus fileStatus = getFileStatus(args);
@@ -2015,7 +2021,7 @@ public List<OzoneFileStatus> listStatus(OmKeyArgs args, boolean recursive,
20152021
}
20162022
}
20172023
} finally {
2018-
metadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
2024+
metadataManager.getLock().releaseReadLock(BUCKET_LOCK, volumeName,
20192025
bucketName);
20202026
}
20212027
return fileStatusList;

0 commit comments

Comments
 (0)