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]

Reply via email to