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 7c6b435eb0 HDDS-8742. Quota repair counts of namespace and space
usages (#4817)
7c6b435eb0 is described below
commit 7c6b435eb08d09f5166c61b84176d3978bd22f80
Author: Sumit Agrawal <[email protected]>
AuthorDate: Mon Jun 19 10:56:30 2023 +0530
HDDS-8742. Quota repair counts of namespace and space usages (#4817)
---
.../common/src/main/resources/ozone-default.xml | 10 +
.../org/apache/hadoop/ozone/om/OMConfigKeys.java | 3 +
.../hadoop/ozone/om/service/QuotaRepairTask.java | 326 +++++++++++++++++++++
.../hadoop/ozone/om/upgrade/OMLayoutFeature.java | 4 +-
.../ozone/om/upgrade/QuotaRepairUpgradeAction.java | 45 +++
.../ozone/om/service/TestQuotaRepairTask.java | 93 ++++++
6 files changed, 480 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 9849ae88bd..10c0dfc776 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -4062,4 +4062,14 @@
https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator.
</description>
</property>
+ <property>
+ <name>ozone.om.upgrade.quota.recalculate.enabled</name>
+ <value>true</value>
+ <tag>OZONE, OM</tag>
+ <description>
+ quota recalculation trigger when upgrade to the layout version QUOTA.
+ while upgrade, re-calculation of quota used will block write operation
+ to existing buckets till this operation is completed.
+ </description>
+ </property>
</configuration>
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 e6df3e5946..bdf38f33bf 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
@@ -536,4 +536,7 @@ public final class OMConfigKeys {
public static final long
OZONE_OM_SNAPSHOT_DIFF_MAX_ALLOWED_KEYS_CHANGED_PER_DIFF_JOB_DEFAULT
= 10_000_000;
+
+ public static final String OZONE_OM_UPGRADE_QUOTA_RECALCULATE_ENABLE
+ = "ozone.om.upgrade.quota.recalculate.enabled";
}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java
new file mode 100644
index 0000000000..661f7998c0
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hadoop.ozone.om.service;
+
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.hdds.utils.db.Table;
+import org.apache.hadoop.hdds.utils.db.TableIterator;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.helpers.BucketLayout;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
+import org.apache.hadoop.ozone.om.lock.IOzoneManagerLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX;
+import static
org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.BUCKET_LOCK;
+
+/**
+ * Quota repair task.
+ */
+public class QuotaRepairTask {
+ private static final Logger LOG = LoggerFactory.getLogger(
+ QuotaRepairTask.class);
+ private static final int BATCH_SIZE = 5000;
+ private static final int TASK_THREAD_CNT = 3;
+ private final OMMetadataManager metadataManager;
+ private final Map<String, OmBucketInfo> nameBucketInfoMap = new HashMap<>();
+ private final Map<String, OmBucketInfo> idBucketInfoMap = new HashMap<>();
+ private ExecutorService executor;
+ private final Map<String, CountPair> keyCountMap = new ConcurrentHashMap<>();
+ private final Map<String, CountPair> fileCountMap
+ = new ConcurrentHashMap<>();
+ private final Map<String, CountPair> directoryCountMap
+ = new ConcurrentHashMap<>();
+
+ public QuotaRepairTask(OMMetadataManager metadataManager) {
+ this.metadataManager = metadataManager;
+ }
+
+ public void repair() throws Exception {
+ LOG.info("Starting quota repair task");
+ prepareAllVolumeBucketInfo();
+
+ IOzoneManagerLock lock = metadataManager.getLock();
+ // thread pool with 3 Table type * (1 task each + 3 thread each)
+ executor = Executors.newFixedThreadPool(12);
+ try {
+ nameBucketInfoMap.values().stream().forEach(e -> lock.acquireReadLock(
+ BUCKET_LOCK, e.getVolumeName(), e.getBucketName()));
+ repairCount();
+ } finally {
+ nameBucketInfoMap.values().stream().forEach(e -> lock.releaseReadLock(
+ BUCKET_LOCK, e.getVolumeName(), e.getBucketName()));
+ executor.shutdown();
+ LOG.info("Completed quota repair task");
+ }
+ }
+
+ private void prepareAllVolumeBucketInfo() throws IOException {
+ try (TableIterator<String, ? extends Table.KeyValue<String, OmVolumeArgs>>
+ iterator = metadataManager.getVolumeTable().iterator()) {
+
+ OmVolumeArgs omVolumeArgs;
+ while (iterator.hasNext()) {
+ Table.KeyValue<String, OmVolumeArgs> entry =
+ iterator.next();
+ omVolumeArgs = entry.getValue();
+ getAllBuckets(omVolumeArgs.getVolume(), omVolumeArgs.getObjectID());
+ }
+ }
+ }
+
+ private void getAllBuckets(String volumeName, long volumeId)
+ throws IOException {
+ List<OmBucketInfo> bucketList = metadataManager.listBuckets(
+ volumeName, null, null, Integer.MAX_VALUE, false);
+ for (OmBucketInfo bucketInfo : bucketList) {
+ bucketInfo.incrUsedNamespace(-bucketInfo.getUsedNamespace());
+ bucketInfo.incrUsedBytes(-bucketInfo.getUsedBytes());
+ nameBucketInfoMap.put(buildNamePath(volumeName,
+ bucketInfo.getBucketName()), bucketInfo);
+ idBucketInfoMap.put(buildIdPath(volumeId, bucketInfo.getObjectID()),
+ bucketInfo);
+ }
+ }
+
+ private String buildNamePath(String volumeName, String bucketName) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(OM_KEY_PREFIX)
+ .append(volumeName)
+ .append(OM_KEY_PREFIX)
+ .append(bucketName)
+ .append(OM_KEY_PREFIX);
+ return builder.toString();
+ }
+
+ private String buildIdPath(long volumeId, long bucketId) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(OM_KEY_PREFIX)
+ .append(volumeId)
+ .append(OM_KEY_PREFIX)
+ .append(bucketId)
+ .append(OM_KEY_PREFIX);
+ return builder.toString();
+ }
+
+ private void repairCount() throws Exception {
+ LOG.info("Starting quota repair for all keys, files and directories");
+ try {
+ nameBucketInfoMap.keySet().stream().forEach(e -> keyCountMap.put(e,
+ new CountPair()));
+ idBucketInfoMap.keySet().stream().forEach(e -> fileCountMap.put(e,
+ new CountPair()));
+ idBucketInfoMap.keySet().stream().forEach(e -> directoryCountMap.put(e,
+ new CountPair()));
+
+ List<Future<?>> tasks = new ArrayList<>();
+ tasks.add(executor.submit(() -> recalculateUsages(
+ metadataManager.getKeyTable(BucketLayout.OBJECT_STORE),
+ keyCountMap, "Key usages", true)));
+ tasks.add(executor.submit(() -> recalculateUsages(
+ metadataManager.getKeyTable(BucketLayout.FILE_SYSTEM_OPTIMIZED),
+ fileCountMap, "File usages", true)));
+ tasks.add(executor.submit(() -> recalculateUsages(
+ metadataManager.getDirectoryTable(),
+ directoryCountMap, "Directory usages", false)));
+ for (Future<?> f : tasks) {
+ f.get();
+ }
+ } catch (UncheckedIOException ex) {
+ LOG.error("quota repair failure", ex.getCause());
+ throw ex.getCause();
+ } catch (UncheckedExecutionException ex) {
+ LOG.error("quota repair failure", ex.getCause());
+ throw new Exception(ex.getCause());
+ }
+
+ // persist bucket info
+ updateCountToBucketInfo(nameBucketInfoMap, keyCountMap);
+ updateCountToBucketInfo(idBucketInfoMap, fileCountMap);
+ updateCountToBucketInfo(idBucketInfoMap, directoryCountMap);
+
+ try (BatchOperation batchOperation = metadataManager.getStore()
+ .initBatchOperation()) {
+ for (Map.Entry<String, OmBucketInfo> entry
+ : nameBucketInfoMap.entrySet()) {
+ String bucketKey = metadataManager.getBucketKey(
+ entry.getValue().getVolumeName(),
+ entry.getValue().getBucketName());
+ metadataManager.getBucketTable().putWithBatch(batchOperation,
+ bucketKey, entry.getValue());
+ }
+ metadataManager.getStore().commitBatchOperation(batchOperation);
+ }
+ LOG.info("Completed quota repair for all keys, files and directories");
+ }
+
+ private <VALUE> void recalculateUsages(
+ Table<String, VALUE> table, Map<String, CountPair> prefixUsageMap,
+ String strType, boolean haveValue) throws UncheckedIOException,
+ UncheckedExecutionException {
+ LOG.info("Starting recalculate {}", strType);
+
+ List<Table.KeyValue<String, VALUE>> kvList = new ArrayList<>(BATCH_SIZE);
+ BlockingQueue<List<Table.KeyValue<String, VALUE>>> q
+ = new ArrayBlockingQueue<>(TASK_THREAD_CNT);
+ List<Future<?>> tasks = new ArrayList<>();
+ AtomicBoolean isRunning = new AtomicBoolean(true);
+ for (int i = 0; i < TASK_THREAD_CNT; ++i) {
+ tasks.add(executor.submit(() -> captureCount(
+ prefixUsageMap, q, isRunning, haveValue)));
+ }
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ try (TableIterator<String, ? extends Table.KeyValue<String, VALUE>>
+ keyIter = table.iterator()) {
+ while (keyIter.hasNext()) {
+ count++;
+ kvList.add(keyIter.next());
+ if (kvList.size() == BATCH_SIZE) {
+ q.put(kvList);
+ kvList = new ArrayList<>(BATCH_SIZE);
+ }
+ }
+ q.put(kvList);
+ isRunning.set(false);
+ for (Future<?> f : tasks) {
+ f.get();
+ }
+ LOG.info("Recalculate {} completed, count {} time {}ms", strType,
+ count, (System.currentTimeMillis() - startTime));
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ } catch (ExecutionException ex) {
+ throw new UncheckedExecutionException(ex);
+ }
+ }
+
+ private <VALUE> void captureCount(
+ Map<String, CountPair> prefixUsageMap,
+ BlockingQueue<List<Table.KeyValue<String, VALUE>>> q,
+ AtomicBoolean isRunning, boolean haveValue) throws UncheckedIOException {
+ try {
+ while (isRunning.get() || !q.isEmpty()) {
+ List<Table.KeyValue<String, VALUE>> kvList
+ = q.poll(100, TimeUnit.MILLISECONDS);
+ if (null != kvList) {
+ for (Table.KeyValue<String, VALUE> kv : kvList) {
+ extractCount(kv, prefixUsageMap, haveValue);
+ }
+ }
+ }
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private <VALUE> void extractCount(
+ Table.KeyValue<String, VALUE> kv,
+ Map<String, CountPair> prefixUsageMap,
+ boolean haveValue) {
+ try {
+ String prefix = getVolumeBucketPrefix(kv.getKey());
+ CountPair usage = prefixUsageMap.get(prefix);
+ if (null == usage) {
+ return;
+ }
+ usage.incrNamespace(1L);
+ // avoid decode of value
+ if (haveValue) {
+ VALUE value = kv.getValue();
+ if (value instanceof OmKeyInfo) {
+ usage.incrSpace(((OmKeyInfo) value).getReplicatedSize());
+ }
+ }
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
+ private synchronized void updateCountToBucketInfo(
+ Map<String, OmBucketInfo> bucketInfoMap,
+ Map<String, CountPair> prefixUsageMap) {
+ for (Map.Entry<String, CountPair> entry : prefixUsageMap.entrySet()) {
+ // update bucket info if available
+ OmBucketInfo omBucketInfo = bucketInfoMap.get(entry.getKey());
+ if (omBucketInfo != null) {
+ omBucketInfo.incrUsedBytes(entry.getValue().getSpace());
+ omBucketInfo.incrUsedNamespace(entry.getValue().getNamespace());
+ }
+ }
+ }
+
+ private String getVolumeBucketPrefix(String key) {
+ // get bucket prefix with /<volume>/<bucket>/
+ // -- as represents name in OBS and id in FSO
+ String prefix = key;
+ int idx = key.indexOf(OM_KEY_PREFIX, 1);
+ if (idx != -1) {
+ idx = key.indexOf(OM_KEY_PREFIX, idx + 1);
+ if (idx != -1) {
+ prefix = key.substring(0, idx + 1);
+ }
+ }
+ return prefix;
+ }
+
+ private static class CountPair {
+ private AtomicLong space = new AtomicLong();
+ private AtomicLong namespace = new AtomicLong();
+
+ public void incrSpace(long val) {
+ space.getAndAdd(val);
+ }
+
+ public void incrNamespace(long val) {
+ namespace.getAndAdd(val);
+ }
+
+ public long getSpace() {
+ return space.get();
+ }
+
+ public long getNamespace() {
+ return namespace.get();
+ }
+ }
+}
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeature.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeature.java
index 74160b88a1..d931c128a9 100644
---
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeature.java
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/OMLayoutFeature.java
@@ -42,7 +42,9 @@ public enum OMLayoutFeature implements LayoutFeature {
HSYNC(4, "Support hsync"),
- FILESYSTEM_SNAPSHOT(5, "Ozone version supporting snapshot");
+ FILESYSTEM_SNAPSHOT(5, "Ozone version supporting snapshot"),
+
+ QUOTA(6, "Ozone quota re-calculate");
/////////////////////////////// /////////////////////////////
// Example OM Layout Feature with Actions
diff --git
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/QuotaRepairUpgradeAction.java
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/QuotaRepairUpgradeAction.java
new file mode 100644
index 0000000000..a0218d42d9
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/upgrade/QuotaRepairUpgradeAction.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hadoop.ozone.om.upgrade;
+
+import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.service.QuotaRepairTask;
+
+import static org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.QUOTA;
+import static
org.apache.hadoop.ozone.upgrade.LayoutFeature.UpgradeActionType.ON_FIRST_UPGRADE_START;
+
+/**
+ * Quota repair for usages action to be triggered during first upgrade.
+ */
+@UpgradeActionOm(type = ON_FIRST_UPGRADE_START, feature =
+ QUOTA)
+public class QuotaRepairUpgradeAction implements OmUpgradeAction {
+ @Override
+ public void execute(OzoneManager arg) throws Exception {
+ boolean enabled = arg.getConfiguration().getBoolean(
+ OMConfigKeys.OZONE_OM_UPGRADE_QUOTA_RECALCULATE_ENABLE, false);
+ if (enabled) {
+ QuotaRepairTask quotaRepairTask = new QuotaRepairTask(
+ arg.getMetadataManager());
+ quotaRepairTask.repair();
+ }
+ }
+}
diff --git
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestQuotaRepairTask.java
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestQuotaRepairTask.java
new file mode 100644
index 0000000000..439137e3ed
--- /dev/null
+++
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/service/TestQuotaRepairTask.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hadoop.ozone.om.service;
+
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import org.apache.hadoop.ozone.om.helpers.BucketLayout;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
+import org.apache.hadoop.ozone.om.request.key.TestOMKeyRequest;
+import org.apache.hadoop.util.Time;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test class for quota repair.
+ */
+public class TestQuotaRepairTask extends TestOMKeyRequest {
+
+ @Test
+ public void testQuotaRepair() throws Exception {
+ OMRequestTestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
+ omMetadataManager, BucketLayout.OBJECT_STORE);
+
+ int count = 10;
+ String parentDir = "/user";
+ for (int i = 0; i < count; i++) {
+ OMRequestTestUtils.addKeyToTableAndCache(volumeName, bucketName,
+ parentDir.concat("/key" + i), -1, HddsProtos.ReplicationType.RATIS,
+ HddsProtos.ReplicationFactor.THREE, 150 + i, omMetadataManager);
+ }
+
+ String fsoBucketName = "fso" + bucketName;
+ OMRequestTestUtils.addBucketToDB(volumeName, fsoBucketName,
+ omMetadataManager, BucketLayout.FILE_SYSTEM_OPTIMIZED);
+ long parentId = OMRequestTestUtils.addParentsToDirTable(volumeName,
+ fsoBucketName, "c/d/e", omMetadataManager);
+ for (int i = 0; i < count; i++) {
+ String fileName = "file1" + i;
+ OmKeyInfo omKeyInfo = OMRequestTestUtils.createOmKeyInfo(
+ volumeName, fsoBucketName, fileName,
+ HddsProtos.ReplicationType.RATIS,
+ HddsProtos.ReplicationFactor.ONE,
+ parentId + 1 + i,
+ parentId, 100 + i, Time.now());
+ omKeyInfo.setKeyName(fileName);
+ OMRequestTestUtils.addFileToKeyTable(false, false,
+ fileName, omKeyInfo, -1, 50 + i, omMetadataManager);
+ }
+
+ // all count is 0 as above is adding directly to key / file table
+ // and directory table
+ OmBucketInfo obsBucketInfo = omMetadataManager.getBucketTable().get(
+ omMetadataManager.getBucketKey(volumeName, bucketName));
+ Assert.assertTrue(obsBucketInfo.getUsedNamespace() == 0);
+ Assert.assertTrue(obsBucketInfo.getUsedBytes() == 0);
+ OmBucketInfo fsoBucketInfo = omMetadataManager.getBucketTable().get(
+ omMetadataManager.getBucketKey(volumeName, fsoBucketName));
+ Assert.assertTrue(fsoBucketInfo.getUsedNamespace() == 0);
+ Assert.assertTrue(fsoBucketInfo.getUsedBytes() == 0);
+
+ QuotaRepairTask quotaRepairTask = new QuotaRepairTask(omMetadataManager);
+ quotaRepairTask.repair();
+
+ // 10 files of each type, obs have replication of three and
+ // fso have replication of one
+ OmBucketInfo obsUpdateBucketInfo = omMetadataManager.getBucketTable().get(
+ omMetadataManager.getBucketKey(volumeName, bucketName));
+ OmBucketInfo fsoUpdateBucketInfo = omMetadataManager.getBucketTable().get(
+ omMetadataManager.getBucketKey(volumeName, fsoBucketName));
+ Assert.assertTrue(obsUpdateBucketInfo.getUsedNamespace() == 10);
+ Assert.assertTrue(obsUpdateBucketInfo.getUsedBytes() == 30000);
+ Assert.assertTrue(fsoUpdateBucketInfo.getUsedNamespace() == 13);
+ Assert.assertTrue(fsoUpdateBucketInfo.getUsedBytes() == 10000);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]