This is an automated email from the ASF dual-hosted git repository.
sshenoy 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 a4b23971be HDDS-9803. Limit total number of buckets to avoid
OutOfMemoryError in OM. (#5705)
a4b23971be is described below
commit a4b23971be395f4ef77ec2a88414fc1bcd5d421e
Author: Sumit Agrawal <[email protected]>
AuthorDate: Thu Dec 7 13:56:34 2023 +0530
HDDS-9803. Limit total number of buckets to avoid OutOfMemoryError in OM.
(#5705)
---
.../common/src/main/resources/ozone-default.xml | 8 ++++++++
.../org/apache/hadoop/hdds/utils/db/TypedTable.java | 3 +++
.../hadoop/hdds/utils/db/cache/FullTableCache.java | 5 +++++
.../hdds/utils/db/cache/PartialTableCache.java | 5 +++++
.../hadoop/hdds/utils/db/cache/TableCache.java | 5 +++++
.../org/apache/hadoop/ozone/om/OMConfigKeys.java | 4 ++++
.../hadoop/ozone/om/exceptions/OMException.java | 4 +++-
.../src/main/proto/OmClientProtocol.proto | 2 ++
.../om/request/bucket/OMBucketCreateRequest.java | 20 ++++++++++++++++++++
.../om/request/TestOMClientRequestWithUserInfo.java | 1 +
.../om/request/bucket/TestOMBucketCreateRequest.java | 16 ++++++++++++++++
11 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml
b/hadoop-hdds/common/src/main/resources/ozone-default.xml
index db16381634..d0c8f4e2bd 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -4271,4 +4271,12 @@
Specify if zero-copy should be enabled for EC GRPC protocol.
</description>
</property>
+ <property>
+ <name>ozone.om.max.buckets</name>
+ <value>100000</value>
+ <tag>OZONE, OM</tag>
+ <description>
+ maximum number of buckets across all volumes.
+ </description>
+ </property>
</configuration>
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
index e668413a83..761357f38a 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/TypedTable.java
@@ -441,6 +441,9 @@ public class TypedTable<KEY, VALUE> implements Table<KEY,
VALUE> {
@Override
public long getEstimatedKeyCount() throws IOException {
+ if (cache.getCacheType() == CacheType.FULL_CACHE) {
+ return cache.size();
+ }
return rawTable.getEstimatedKeyCount();
}
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/FullTableCache.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/FullTableCache.java
index e99fcb4165..cb1a3f16a9 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/FullTableCache.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/FullTableCache.java
@@ -210,4 +210,9 @@ public class FullTableCache<KEY, VALUE> implements
TableCache<KEY, VALUE> {
public CacheStats getStats() {
return statsRecorder.snapshot();
}
+
+ @Override
+ public CacheType getCacheType() {
+ return CacheType.FULL_CACHE;
+ }
}
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/PartialTableCache.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/PartialTableCache.java
index c40c4804b5..7f304810ff 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/PartialTableCache.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/PartialTableCache.java
@@ -188,4 +188,9 @@ public class PartialTableCache<KEY, VALUE> implements
TableCache<KEY, VALUE> {
public CacheStats getStats() {
return statsRecorder.snapshot();
}
+
+ @Override
+ public CacheType getCacheType() {
+ return CacheType.PARTIAL_CACHE;
+ }
}
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/TableCache.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/TableCache.java
index d104e40a55..62de974eac 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/TableCache.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/db/cache/TableCache.java
@@ -105,6 +105,11 @@ public interface TableCache<KEY, VALUE> {
*/
CacheStats getStats();
+ /**
+ * Return the cache type.
+ */
+ CacheType getCacheType();
+
/**
* Cache completeness.
*/
diff --git
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
index 9b15326550..72a8d4fdc2 100644
---
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
+++
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java
@@ -586,4 +586,8 @@ public final class OMConfigKeys {
public static final boolean OZONE_OM_UPGRADE_QUOTA_RECALCULATE_ENABLE_DEFAULT
= true;
+
+ public static final String OZONE_OM_MAX_BUCKET =
+ "ozone.om.max.buckets";
+ public static final int OZONE_OM_MAX_BUCKET_DEFAULT = 100000;
}
diff --git
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
index 20b4fb1ed0..2e5a196852 100644
---
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
+++
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java
@@ -267,6 +267,8 @@ public class OMException extends IOException {
S3_SECRET_ALREADY_EXISTS,
- INVALID_PATH
+ INVALID_PATH,
+
+ TOO_MANY_BUCKETS
}
}
diff --git
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 54cafbc0ad..fd83981507 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -524,6 +524,8 @@ enum Status {
S3_SECRET_ALREADY_EXISTS = 92;
INVALID_PATH = 93;
+
+ TOO_MANY_BUCKETS = 94;
}
/**
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
index 58fad4a3d2..0b90fc38d2 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java
@@ -31,6 +31,7 @@ import org.apache.hadoop.ozone.OzoneAcl;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.audit.OMAction;
+import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OMMetrics;
import org.apache.hadoop.ozone.om.OzoneManager;
@@ -97,6 +98,8 @@ public class OMBucketCreateRequest extends OMClientRequest {
OmUtils.validateBucketName(bucketInfo.getBucketName(),
ozoneManager.isStrictS3());
+ validateMaxBucket(ozoneManager);
+
// Get KMS provider.
KeyProviderCryptoExtension kmsProvider =
ozoneManager.getKmsProvider();
@@ -142,6 +145,23 @@ public class OMBucketCreateRequest extends OMClientRequest
{
.setCreateBucketRequest(newCreateBucketRequest.build()).build();
}
+ private static void validateMaxBucket(OzoneManager ozoneManager)
+ throws IOException {
+ int maxBucket = ozoneManager.getConfiguration().getInt(
+ OMConfigKeys.OZONE_OM_MAX_BUCKET,
+ OMConfigKeys.OZONE_OM_MAX_BUCKET_DEFAULT);
+ if (maxBucket <= 0) {
+ maxBucket = OMConfigKeys.OZONE_OM_MAX_BUCKET_DEFAULT;
+ }
+ long nrOfBuckets = ozoneManager.getMetadataManager().getBucketTable()
+ .getEstimatedKeyCount();
+ if (nrOfBuckets >= maxBucket) {
+ throw new OMException("Cannot create more than " + maxBucket
+ + " buckets",
+ ResultCodes.TOO_MANY_BUCKETS);
+ }
+ }
+
@Override
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
long transactionLogIndex,
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
index 299a8d5652..3a43485278 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMClientRequestWithUserInfo.java
@@ -81,6 +81,7 @@ public class TestOMClientRequestWithUserInfo {
ozoneManager);
when(ozoneManager.getMetrics()).thenReturn(omMetrics);
when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager);
+ when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);
inetAddress = InetAddress.getByName("127.0.0.1");
}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
index 831d670e41..cbfd3f8874 100644
---
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/bucket/TestOMBucketCreateRequest.java
@@ -23,6 +23,7 @@ import java.util.UUID;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
+import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.junit.jupiter.api.Assertions;
@@ -65,6 +66,21 @@ public class TestOMBucketCreateRequest extends
TestBucketRequest {
assertEquals("Invalid bucket name: b1", omException.getMessage());
}
+ @Test
+ public void preExecuteBucketCrossesMaxLimit() throws Exception {
+ ozoneManager.getConfiguration().setInt(
+ OMConfigKeys.OZONE_OM_MAX_BUCKET, 1);
+ String volumeName = UUID.randomUUID().toString();
+ String bucketName = UUID.randomUUID().toString();
+ OMBucketCreateRequest omBucketCreateRequest = doPreExecute(volumeName,
+ bucketName);
+ doValidateAndUpdateCache(volumeName, bucketName,
+ omBucketCreateRequest.getOmRequest());
+ OMException omException = assertThrows(OMException.class,
+ () -> doPreExecute("volume2", "test2"));
+ assertEquals("Cannot create more than 1 buckets",
omException.getMessage());
+ }
+
@Test
public void testValidateAndUpdateCache() throws Exception {
String volumeName = UUID.randomUUID().toString();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]