This is an automated email from the ASF dual-hosted git repository.
szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new d6012190454 HDDS-15907. Do not use Collection in IOzoneManagerLock.
(#10907)
d6012190454 is described below
commit d601219045421721d52f0e00cf23bf7c67280fd6
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Fri Jul 31 11:37:34 2026 -0700
HDDS-15907. Do not use Collection in IOzoneManagerLock. (#10907)
---
.../hadoop/ozone/om/lock/IOzoneManagerLock.java | 12 +-
.../hadoop/ozone/om/lock/OmReadOnlyLock.java | 10 +-
.../hadoop/ozone/om/lock/OzoneManagerLock.java | 163 ++++++++++++++-------
.../snapshot/OMSnapshotMoveTableKeysResponse.java | 7 +-
.../TestOMSnapshotMoveTableKeysResponse.java | 6 +-
5 files changed, 123 insertions(+), 75 deletions(-)
diff --git
a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/lock/IOzoneManagerLock.java
b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/lock/IOzoneManagerLock.java
index 66029caf7ff..e9319a787e7 100644
---
a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/lock/IOzoneManagerLock.java
+++
b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/lock/IOzoneManagerLock.java
@@ -18,7 +18,6 @@
package org.apache.hadoop.ozone.om.lock;
import com.google.common.annotations.VisibleForTesting;
-import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.ratis.util.function.UncheckedAutoCloseableSupplier;
@@ -30,13 +29,12 @@ public interface IOzoneManagerLock {
OMLockDetails acquireReadLock(Resource resource,
String... resources);
- OMLockDetails acquireReadLocks(Resource resource, Collection<String[]>
resources);
+ OMLockDetails acquireReadLocks(Resource resource, Iterable<String[]> keys);
OMLockDetails acquireWriteLock(Resource resource,
String... resources);
- OMLockDetails acquireWriteLocks(Resource resource,
- Collection<String[]> resources);
+ OMLockDetails acquireWriteLocks(Resource resource, Iterable<String[]> keys);
OMLockDetails acquireResourceWriteLock(Resource resource);
@@ -47,16 +45,14 @@ OMLockDetails acquireWriteLocks(Resource resource,
OMLockDetails releaseWriteLock(Resource resource,
String... resources);
- OMLockDetails releaseWriteLocks(Resource resource,
- Collection<String[]> resources);
+ OMLockDetails releaseWriteLocks(Resource resource, Iterable<String[]> keys);
OMLockDetails releaseResourceWriteLock(Resource resource);
OMLockDetails releaseReadLock(Resource resource,
String... resources);
- OMLockDetails releaseReadLocks(Resource resource,
- Collection<String[]> resources);
+ OMLockDetails releaseReadLocks(Resource resource, Iterable<String[]> keys);
@VisibleForTesting
int getReadHoldCount(Resource resource,
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OmReadOnlyLock.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OmReadOnlyLock.java
index faf5ca99b8c..7e544b01020 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OmReadOnlyLock.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OmReadOnlyLock.java
@@ -20,8 +20,6 @@
import static
org.apache.hadoop.ozone.om.lock.OMLockDetails.EMPTY_DETAILS_LOCK_ACQUIRED;
import static
org.apache.hadoop.ozone.om.lock.OMLockDetails.EMPTY_DETAILS_LOCK_NOT_ACQUIRED;
-import java.util.Collection;
-
/**
* Read only "lock" for snapshots
* Uses no lock. Always returns true when acquiring
@@ -35,7 +33,7 @@ public OMLockDetails acquireReadLock(Resource resource,
String... resources) {
}
@Override
- public OMLockDetails acquireReadLocks(Resource resource,
Collection<String[]> resources) {
+ public OMLockDetails acquireReadLocks(Resource resource, Iterable<String[]>
keys) {
return EMPTY_DETAILS_LOCK_ACQUIRED;
}
@@ -46,7 +44,7 @@ public OMLockDetails acquireWriteLock(Resource resource,
}
@Override
- public OMLockDetails acquireWriteLocks(Resource resource,
Collection<String[]> resources) {
+ public OMLockDetails acquireWriteLocks(Resource resource, Iterable<String[]>
keys) {
return EMPTY_DETAILS_LOCK_NOT_ACQUIRED;
}
@@ -72,7 +70,7 @@ public OMLockDetails releaseWriteLock(Resource resource,
}
@Override
- public OMLockDetails releaseWriteLocks(Resource resource,
Collection<String[]> resources) {
+ public OMLockDetails releaseWriteLocks(Resource resource, Iterable<String[]>
keys) {
return EMPTY_DETAILS_LOCK_NOT_ACQUIRED;
}
@@ -87,7 +85,7 @@ public OMLockDetails releaseReadLock(Resource resource,
String... resources) {
}
@Override
- public OMLockDetails releaseReadLocks(Resource resource,
Collection<String[]> resources) {
+ public OMLockDetails releaseReadLocks(Resource resource, Iterable<String[]>
keys) {
return EMPTY_DETAILS_LOCK_NOT_ACQUIRED;
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OzoneManagerLock.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OzoneManagerLock.java
index b0abd85f944..a6a47844519 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OzoneManagerLock.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/lock/OzoneManagerLock.java
@@ -24,26 +24,27 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.Striped;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
+import java.util.Deque;
import java.util.EnumMap;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
+import java.util.RandomAccess;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.function.Function;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-import java.util.stream.StreamSupport;
import org.apache.hadoop.hdds.conf.ConfigurationSource;
import org.apache.hadoop.hdds.utils.CompositeKey;
import org.apache.hadoop.hdds.utils.SimpleStriped;
import org.apache.hadoop.ipc_.ProcessingDetails.Timing;
import org.apache.hadoop.ipc_.Server;
import org.apache.hadoop.util.Time;
+import org.apache.ratis.util.CollectionUtils;
import org.apache.ratis.util.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -140,24 +141,38 @@ private void acquireLock(R resource, boolean isRead,
ReentrantReadWriteLock lock
}
}
- OMLockDetails acquire(Resource resource, boolean isRead,
- Function<Striped<ReentrantReadWriteLock>,
Iterable<ReentrantReadWriteLock>> getLocks) {
+ private OMLockDetails acquireImpl(Resource resource, BiConsumer<R, Long>
acquireLockMethod) {
final R r = assertAcquire(resource);
final long startWaitingTimeNanos = Time.monotonicNowNanos();
- for (ReentrantReadWriteLock lock : getLocks.apply(lockMap.get(r))) {
- acquireLock(r, isRead, lock, startWaitingTimeNanos);
- }
+ acquireLockMethod.accept(r, startWaitingTimeNanos);
return tracker.lockResource(r);
}
- OMLockDetails acquire(Resource resource, boolean isRead, String... keys) {
- final R r = assertAcquire(resource);
- final long startWaitingTimeNanos = Time.monotonicNowNanos();
- acquireLock(r, isRead, getLock(r, keys), startWaitingTimeNanos);
- return tracker.lockResource(r);
+ private OMLockDetails acquireOne(Resource resource, boolean isRead,
String... keys) {
+ return acquireImpl(resource, (r, startWaitingTimeNanos) -> {
+ final ReentrantReadWriteLock lock = getLock(r, keys);
+ acquireLock(r, isRead, lock, startWaitingTimeNanos);
+ });
}
- void releaseLock(R resource, boolean isRead, ReentrantReadWriteLock lock) {
+ private OMLockDetails acquireAll(Resource resource) {
+ return acquireImpl(resource, (r, startWaitingTimeNanos) -> {
+ final Striped<ReentrantReadWriteLock> striped = lockMap.get(r);
+ for (int i = 0; i < striped.size(); i++) {
+ acquireLock(r, false, striped.getAt(i), startWaitingTimeNanos);
+ }
+ });
+ }
+
+ private OMLockDetails acquireSelected(Resource resource, boolean isRead,
Iterable<String[]> keys) {
+ return acquireImpl(resource, (r, startWaitingTimeNanos) -> {
+ for (ReentrantReadWriteLock lock : bulkGetForAcquire(lockMap.get(r),
keys)) {
+ acquireLock(r, isRead, lock, startWaitingTimeNanos);
+ }
+ });
+ }
+
+ private void releaseLock(R resource, boolean isRead,
ReentrantReadWriteLock lock) {
if (isRead) {
lock.readLock().unlock();
updateReadUnlockMetrics(resource, tracker, lock);
@@ -168,27 +183,36 @@ void releaseLock(R resource, boolean isRead,
ReentrantReadWriteLock lock) {
}
}
- OMLockDetails release(Resource resource, boolean isRead, String... keys) {
+ private OMLockDetails releaseImpl(Resource resource, Consumer<R>
releaseLockMethod) {
final R r = Preconditions.assertInstanceOf(resource,
tracker.getResourceClass());
tracker.clearLockDetails();
- final ReentrantReadWriteLock lock = getLock(r, keys);
- releaseLock(r, isRead, lock);
+ releaseLockMethod.accept(r);
return tracker.unlockResource(r);
}
- private OMLockDetails release(Resource resource, boolean isRead,
- Function<Striped<ReentrantReadWriteLock>,
Iterable<ReentrantReadWriteLock>> getLock) {
- final R r = Preconditions.assertInstanceOf(resource,
tracker.getResourceClass());
- tracker.clearLockDetails();
- final Iterable<ReentrantReadWriteLock> i = getLock.apply(lockMap.get(r));
- final List<ReentrantReadWriteLock> locks =
StreamSupport.stream(i.spliterator(), false)
- .collect(Collectors.toList());
- // Release locks in reverse order.
- Collections.reverse(locks);
- for (ReentrantReadWriteLock lock : locks) {
+ private OMLockDetails releaseOne(Resource resource, boolean isRead,
String... keys) {
+ return releaseImpl(resource, r -> {
+ final ReentrantReadWriteLock lock = getLock(r, keys);
releaseLock(r, isRead, lock);
- }
- return tracker.unlockResource(r);
+ });
+ }
+
+ private OMLockDetails releaseAll(Resource resource) {
+ return releaseImpl(resource, r -> {
+ final Striped<ReentrantReadWriteLock> striped = lockMap.get(r);
+ // Release locks in reverse order.
+ for (int i = striped.size() - 1; i >= 0; i--) {
+ releaseLock(r, false, striped.getAt(i));
+ }
+ });
+ }
+
+ private OMLockDetails releaseSelected(Resource resource, boolean isRead,
Iterable<String[]> keys) {
+ return releaseImpl(resource, r -> {
+ for (ReentrantReadWriteLock lock : bulkGetForRelease(lockMap.get(r),
keys)) {
+ releaseLock(r, isRead, lock);
+ }
+ });
}
List<String> getCurrentLocks() {
@@ -237,19 +261,48 @@ private static Striped<ReentrantReadWriteLock>
createStripeLock(Resource r, Conf
return SimpleStriped.readWriteLock(size, fair);
}
- private Iterable<ReentrantReadWriteLock>
getAllLocks(Striped<ReentrantReadWriteLock> striped) {
- return IntStream.range(0,
striped.size()).mapToObj(striped::getAt).collect(Collectors.toList());
+ /** @return locks in ascending order for acquire. */
+ static Iterable<ReentrantReadWriteLock> bulkGetForAcquire(
+ Striped<ReentrantReadWriteLock> striped, Iterable<String[]> keys) {
+ return striped.bulkGet(CollectionUtils.as(keys,
CompositeKey::combineKeys)); // no copying
}
- private Iterable<ReentrantReadWriteLock>
bulkGetLock(Striped<ReentrantReadWriteLock> striped,
- Collection<String[]> keys) {
- List<Object> lockKeys = new ArrayList<>(keys.size());
- for (String[] key : keys) {
- if (Objects.nonNull(key)) {
- lockKeys.add(CompositeKey.combineKeys(key));
+ /** @return locks in descending order for release. */
+ static Iterable<ReentrantReadWriteLock> bulkGetForRelease(
+ Striped<ReentrantReadWriteLock> striped, Iterable<String[]> keys) {
+ final Iterable<ReentrantReadWriteLock> iterable =
bulkGetForAcquire(striped, keys);
+
+ // although the return type of Striped.bulkGet(..) is Iterable, its
implementation currently returns an ArrayList.
+ if (iterable instanceof List && iterable instanceof RandomAccess) {
+ final List<ReentrantReadWriteLock> list = (List<ReentrantReadWriteLock>)
iterable;
+ // return in descending order
+ return () -> new Iterator<ReentrantReadWriteLock>() {
+ private int i = list.size() - 1;
+
+ @Override
+ public boolean hasNext() {
+ return i >= 0;
+ }
+
+ @Override
+ public ReentrantReadWriteLock next() {
+ return list.get(i--);
+ }
+ };
+ }
+
+ // use Deque
+ final Deque<ReentrantReadWriteLock> deque;
+ if (iterable instanceof Deque) {
+ deque = (Deque<ReentrantReadWriteLock>) iterable;
+ } else {
+ // fallback copying to a list
+ deque = new LinkedList<>();
+ for (ReentrantReadWriteLock lock : iterable) {
+ deque.add(lock);
}
}
- return striped.bulkGet(lockKeys);
+ return deque::descendingIterator;
}
/**
@@ -272,7 +325,7 @@ private Iterable<ReentrantReadWriteLock>
bulkGetLock(Striped<ReentrantReadWriteL
@Override
public OMLockDetails acquireReadLock(Resource resource, String... keys) {
return getResourceLocks(resource)
- .acquire(resource, true, keys);
+ .acquireOne(resource, true, keys);
}
/**
@@ -293,9 +346,9 @@ public OMLockDetails acquireReadLock(Resource resource,
String... keys) {
* be passed.
*/
@Override
- public OMLockDetails acquireReadLocks(Resource resource,
Collection<String[]> keys) {
+ public OMLockDetails acquireReadLocks(Resource resource, Iterable<String[]>
keys) {
return getResourceLocks(resource)
- .acquire(resource, true, striped -> bulkGetLock(striped, keys));
+ .acquireSelected(resource, true, keys);
}
/**
@@ -318,7 +371,7 @@ public OMLockDetails acquireReadLocks(Resource resource,
Collection<String[]> ke
@Override
public OMLockDetails acquireWriteLock(Resource resource, String... keys) {
return getResourceLocks(resource)
- .acquire(resource, false, keys);
+ .acquireOne(resource, false, keys);
}
/**
@@ -339,9 +392,9 @@ public OMLockDetails acquireWriteLock(Resource resource,
String... keys) {
* be passed.
*/
@Override
- public OMLockDetails acquireWriteLocks(Resource resource,
Collection<String[]> keys) {
+ public OMLockDetails acquireWriteLocks(Resource resource, Iterable<String[]>
keys) {
return getResourceLocks(resource)
- .acquire(resource, false, striped -> bulkGetLock(striped, keys));
+ .acquireSelected(resource, false, keys);
}
/**
@@ -352,7 +405,7 @@ public OMLockDetails acquireWriteLocks(Resource resource,
Collection<String[]> k
@Override
public OMLockDetails acquireResourceWriteLock(Resource resource) {
return getResourceLocks(resource)
- .acquire(resource, false, this::getAllLocks);
+ .acquireAll(resource);
}
private void updateReadLockMetrics(Resource resource, ResourceLockTracker<?
extends Resource> tracker,
@@ -433,7 +486,7 @@ public void releaseMultiUserLock(String firstUser, String
secondUser) {
@Override
public OMLockDetails releaseWriteLock(Resource resource, String... keys) {
return getResourceLocks(resource)
- .release(resource, false, keys);
+ .releaseOne(resource, false, keys);
}
/**
@@ -445,9 +498,9 @@ public OMLockDetails releaseWriteLock(Resource resource,
String... keys) {
* be passed.
*/
@Override
- public OMLockDetails releaseWriteLocks(Resource resource,
Collection<String[]> keys) {
+ public OMLockDetails releaseWriteLocks(Resource resource, Iterable<String[]>
keys) {
return getResourceLocks(resource)
- .release(resource, false, striped -> bulkGetLock(striped, keys));
+ .releaseSelected(resource, false, keys);
}
/**
@@ -458,7 +511,7 @@ public OMLockDetails releaseWriteLocks(Resource resource,
Collection<String[]> k
@Override
public OMLockDetails releaseResourceWriteLock(Resource resource) {
return getResourceLocks(resource)
- .release(resource, false, this::getAllLocks);
+ .releaseAll(resource);
}
/**
@@ -472,7 +525,7 @@ public OMLockDetails releaseResourceWriteLock(Resource
resource) {
@Override
public OMLockDetails releaseReadLock(Resource resource, String... keys) {
return getResourceLocks(resource)
- .release(resource, true, keys);
+ .releaseOne(resource, true, keys);
}
/**
@@ -484,9 +537,9 @@ public OMLockDetails releaseReadLock(Resource resource,
String... keys) {
* be passed.
*/
@Override
- public OMLockDetails releaseReadLocks(Resource resource,
Collection<String[]> keys) {
+ public OMLockDetails releaseReadLocks(Resource resource, Iterable<String[]>
keys) {
return getResourceLocks(resource)
- .release(resource, true, striped -> bulkGetLock(striped, keys));
+ .releaseSelected(resource, true, keys);
}
private void updateReadUnlockMetrics(Resource resource,
ResourceLockTracker<? extends Resource> tracker,
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotMoveTableKeysResponse.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotMoveTableKeysResponse.java
index c9ed469d6ca..e70b35d9403 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotMoveTableKeysResponse.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotMoveTableKeysResponse.java
@@ -21,9 +21,10 @@
import static
org.apache.hadoop.ozone.om.lock.DAGLeveledResource.SNAPSHOT_DB_CONTENT_LOCK;
import static
org.apache.hadoop.ozone.om.snapshot.SnapshotUtils.createMergedRepeatedOmKeyInfoFromDeletedTableEntry;
-import com.google.common.collect.Lists;
import jakarta.annotation.Nonnull;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.utils.db.BatchOperation;
@@ -87,8 +88,8 @@ protected void addToDBBatch(OMMetadataManager
omMetadataManager, BatchOperation
.getOzoneManager().getOmSnapshotManager();
IOzoneManagerLock lock = omMetadataManager.getLock();
String[] fromSnapshotId = new String[]
{fromSnapshot.getSnapshotId().toString()};
- String[] nextSnapshotId = nextSnapshot == null ? null : new String[]
{nextSnapshot.getSnapshotId().toString()};
- List<String[]> snapshotIds = Lists.newArrayList(fromSnapshotId,
nextSnapshotId);
+ final List<String[]> snapshotIds = nextSnapshot == null ?
Collections.singletonList(fromSnapshotId)
+ : Arrays.asList(fromSnapshotId, new
String[]{nextSnapshot.getSnapshotId().toString()});
OMLockDetails lockDetails =
lock.acquireReadLocks(SNAPSHOT_DB_CONTENT_LOCK, snapshotIds);
if (!lockDetails.isLockAcquired()) {
throw new OMException("Unable to acquire read lock on " +
SNAPSHOT_DB_CONTENT_LOCK + " for snapshot: " +
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotMoveTableKeysResponse.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotMoveTableKeysResponse.java
index eb3d2a6612a..696f9ac4f6b 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotMoveTableKeysResponse.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/snapshot/TestOMSnapshotMoveTableKeysResponse.java
@@ -128,9 +128,9 @@ public void testMoveTableKeysToNextSnapshot(boolean
nextSnapshotExists) throws E
getVolumeName(), getBucketName(), snapshotName1);
UncheckedAutoCloseableSupplier<OmSnapshot> snapshot2 =
nextSnapshotExists ? getOmSnapshotManager().getSnapshot(
getVolumeName(), getBucketName(), snapshotName2) : null) {
- List<List<String>> expectedSnapshotIdLocks =
-
Arrays.asList(Collections.singletonList(snapshot1.get().getSnapshotID().toString()),
- nextSnapshotExists ?
Collections.singletonList(snapshot2.get().getSnapshotID().toString()) : null);
+ final List<String> first =
Collections.singletonList(snapshot1.get().getSnapshotID().toString());
+ final List<List<String>> expectedSnapshotIdLocks = !nextSnapshotExists ?
Collections.singletonList(first)
+ : Arrays.asList(first,
Collections.singletonList(snapshot2.get().getSnapshotID().toString()));
List<List<String>> locks = new ArrayList<>();
doAnswer(i -> {
for (String[] id : (Collection<String[]>)i.getArgument(1)) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]