From 8caa5d1ac0c003ccea5157ebd3b6d0d79d6dc774 Mon Sep 17 00:00:00 2001 From: Anu Engineer Date: Wed, 5 Jul 2017 15:23:11 -0700 Subject: [PATCH] HDFS-12086. Ozone: Add the unit test for KSMMetrics. Contributed by Yiqun Lin. --- .../apache/hadoop/ozone/ksm/KSMMetrics.java | 65 ++-- .../hadoop/ozone/ksm/KeySpaceManager.java | 12 +- .../hadoop/ozone/ksm/TestKSMMetrcis.java | 306 ++++++++++++++++++ 3 files changed, 357 insertions(+), 26 deletions(-) create mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/ksm/TestKSMMetrcis.java diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KSMMetrics.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KSMMetrics.java index 1023a171a72..35a4c4384b4 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KSMMetrics.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KSMMetrics.java @@ -18,24 +18,34 @@ package org.apache.hadoop.ozone.ksm; import com.google.common.annotations.VisibleForTesting; + +import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.metrics2.MetricsSystem; import org.apache.hadoop.metrics2.annotation.Metric; +import org.apache.hadoop.metrics2.annotation.Metrics; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; import org.apache.hadoop.metrics2.lib.MutableCounterLong; /** * This class is for maintaining KeySpaceManager statistics. */ +@InterfaceAudience.Private +@Metrics(about="Key Space Manager Metrics", context="dfs") public class KSMMetrics { + // KSM request type op metrics + private @Metric MutableCounterLong numVolumeOps; + private @Metric MutableCounterLong numBucketOps; + private @Metric MutableCounterLong numKeyOps; + // KSM op metrics private @Metric MutableCounterLong numVolumeCreates; - private @Metric MutableCounterLong numVolumeModifies; + private @Metric MutableCounterLong numVolumeUpdates; private @Metric MutableCounterLong numVolumeInfos; private @Metric MutableCounterLong numVolumeCheckAccesses; private @Metric MutableCounterLong numBucketCreates; private @Metric MutableCounterLong numVolumeDeletes; private @Metric MutableCounterLong numBucketInfos; - private @Metric MutableCounterLong numBucketModifies; + private @Metric MutableCounterLong numBucketUpdates; private @Metric MutableCounterLong numBucketDeletes; private @Metric MutableCounterLong numKeyAllocate; private @Metric MutableCounterLong numKeyLookup; @@ -46,13 +56,13 @@ public class KSMMetrics { // Failure Metrics private @Metric MutableCounterLong numVolumeCreateFails; - private @Metric MutableCounterLong numVolumeModifyFails; + private @Metric MutableCounterLong numVolumeUpdateFails; private @Metric MutableCounterLong numVolumeInfoFails; private @Metric MutableCounterLong numVolumeDeleteFails; private @Metric MutableCounterLong numBucketCreateFails; private @Metric MutableCounterLong numVolumeCheckAccessFails; private @Metric MutableCounterLong numBucketInfoFails; - private @Metric MutableCounterLong numBucketModifyFails; + private @Metric MutableCounterLong numBucketUpdateFails; private @Metric MutableCounterLong numBucketDeleteFails; private @Metric MutableCounterLong numKeyAllocateFails; private @Metric MutableCounterLong numKeyLookupFails; @@ -72,50 +82,62 @@ public static KSMMetrics create() { } public void incNumVolumeCreates() { + numVolumeOps.incr(); numVolumeCreates.incr(); } - public void incNumVolumeModifies() { - numVolumeModifies.incr(); + public void incNumVolumeUpdates() { + numVolumeOps.incr(); + numVolumeUpdates.incr(); } public void incNumVolumeInfos() { + numVolumeOps.incr(); numVolumeInfos.incr(); } public void incNumVolumeDeletes() { + numVolumeOps.incr(); numVolumeDeletes.incr(); } public void incNumVolumeCheckAccesses() { + numVolumeOps.incr(); numVolumeCheckAccesses.incr(); } public void incNumBucketCreates() { + numBucketOps.incr(); numBucketCreates.incr(); } public void incNumBucketInfos() { + numBucketOps.incr(); numBucketInfos.incr(); } - public void incNumBucketModifies() { - numBucketModifies.incr(); + public void incNumBucketUpdates() { + numBucketOps.incr(); + numBucketUpdates.incr(); } public void incNumBucketDeletes() { + numBucketOps.incr(); numBucketDeletes.incr(); } public void incNumBucketLists() { + numBucketOps.incr(); numBucketLists.incr(); } public void incNumKeyLists() { + numKeyOps.incr(); numKeyLists.incr(); } public void incNumVolumeLists() { + numVolumeOps.incr(); numVolumeLists.incr(); } @@ -123,8 +145,8 @@ public void incNumVolumeCreateFails() { numVolumeCreateFails.incr(); } - public void incNumVolumeModifyFails() { - numVolumeModifyFails.incr(); + public void incNumVolumeUpdateFails() { + numVolumeUpdateFails.incr(); } public void incNumVolumeInfoFails() { @@ -147,8 +169,8 @@ public void incNumBucketInfoFails() { numBucketInfoFails.incr(); } - public void incNumBucketModifyFails() { - numBucketModifyFails.incr(); + public void incNumBucketUpdateFails() { + numBucketUpdateFails.incr(); } public void incNumBucketDeleteFails() { @@ -156,6 +178,7 @@ public void incNumBucketDeleteFails() { } public void incNumKeyAllocates() { + numKeyOps.incr(); numKeyAllocate.incr(); } @@ -164,6 +187,7 @@ public void incNumKeyAllocateFails() { } public void incNumKeyLookups() { + numKeyOps.incr(); numKeyLookup.incr(); } @@ -176,6 +200,7 @@ public void incNumKeyDeleteFails() { } public void incNumKeyDeletes() { + numKeyOps.incr(); numKeyDeletes.incr(); } @@ -197,8 +222,8 @@ public long getNumVolumeCreates() { } @VisibleForTesting - public long getNumVolumeModifies() { - return numVolumeModifies.value(); + public long getNumVolumeUpdates() { + return numVolumeUpdates.value(); } @VisibleForTesting @@ -227,8 +252,8 @@ public long getNumBucketInfos() { } @VisibleForTesting - public long getNumBucketModifies() { - return numBucketModifies.value(); + public long getNumBucketUpdates() { + return numBucketUpdates.value(); } @VisibleForTesting @@ -257,8 +282,8 @@ public long getNumVolumeCreateFails() { } @VisibleForTesting - public long getNumVolumeModifyFails() { - return numVolumeModifyFails.value(); + public long getNumVolumeUpdateFails() { + return numVolumeUpdateFails.value(); } @VisibleForTesting @@ -287,8 +312,8 @@ public long getNumBucketInfoFails() { } @VisibleForTesting - public long getNumBucketModifyFails() { - return numBucketModifyFails.value(); + public long getNumBucketUpdateFails() { + return numBucketUpdateFails.value(); } @VisibleForTesting diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java index 591d8bfc04e..7cf349cadfb 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java @@ -255,10 +255,10 @@ public void createVolume(KsmVolumeArgs args) throws IOException { @Override public void setOwner(String volume, String owner) throws IOException { try { - metrics.incNumVolumeModifies(); + metrics.incNumVolumeUpdates(); volumeManager.setOwner(volume, owner); } catch (Exception ex) { - metrics.incNumVolumeModifyFails(); + metrics.incNumVolumeUpdateFails(); throw ex; } } @@ -273,10 +273,10 @@ public void setOwner(String volume, String owner) throws IOException { @Override public void setQuota(String volume, long quota) throws IOException { try { - metrics.incNumVolumeModifies(); + metrics.incNumVolumeUpdates(); volumeManager.setQuota(volume, quota); } catch (Exception ex) { - metrics.incNumVolumeModifyFails(); + metrics.incNumVolumeUpdateFails(); throw ex; } } @@ -511,10 +511,10 @@ public List listKeys(String volumeName, String bucketName, public void setBucketProperty(KsmBucketArgs args) throws IOException { try { - metrics.incNumBucketModifies(); + metrics.incNumBucketUpdates(); bucketManager.setBucketProperty(args); } catch (Exception ex) { - metrics.incNumBucketModifyFails(); + metrics.incNumBucketUpdateFails(); throw ex; } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/ksm/TestKSMMetrcis.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/ksm/TestKSMMetrcis.java new file mode 100644 index 00000000000..f23d779f66a --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/ozone/ksm/TestKSMMetrcis.java @@ -0,0 +1,306 @@ +/** + * 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.ksm; + +import static org.apache.hadoop.test.MetricsAsserts.assertCounter; +import static org.apache.hadoop.test.MetricsAsserts.getMetrics; + +import java.io.IOException; + +import org.apache.hadoop.metrics2.MetricsRecordBuilder; +import org.apache.hadoop.ozone.MiniOzoneCluster; +import org.apache.hadoop.ozone.OzoneConfigKeys; +import org.apache.hadoop.ozone.OzoneConfiguration; +import org.apache.hadoop.ozone.OzoneConsts; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.internal.util.reflection.Whitebox; + +/** + * Test for KSM metrics. + */ +public class TestKSMMetrcis { + private MiniOzoneCluster cluster; + private KeySpaceManager ksmManager; + + /** + * The exception used for testing failure metrics. + */ + private IOException exception = new IOException(); + + /** + * Create a MiniDFSCluster for testing. + * + * @throws IOException + */ + @Before + public void setup() throws Exception { + OzoneConfiguration conf = new OzoneConfiguration(); + conf.set(OzoneConfigKeys.OZONE_HANDLER_TYPE_KEY, + OzoneConsts.OZONE_HANDLER_DISTRIBUTED); + cluster = new MiniOzoneCluster.Builder(conf) + .setHandlerType(OzoneConsts.OZONE_HANDLER_DISTRIBUTED).build(); + ksmManager = cluster.getKeySpaceManager(); + } + + /** + * Shutdown MiniDFSCluster. + */ + @After + public void shutdown() { + if (cluster != null) { + cluster.shutdown(); + } + } + + @Test + public void testVolumeOps() throws IOException { + VolumeManager volumeManager = (VolumeManager) Whitebox + .getInternalState(ksmManager, "volumeManager"); + VolumeManager mockVm = Mockito.spy(volumeManager); + + Mockito.doNothing().when(mockVm).createVolume(null); + Mockito.doNothing().when(mockVm).deleteVolume(null); + Mockito.doReturn(null).when(mockVm).getVolumeInfo(null); + Mockito.doReturn(true).when(mockVm).checkVolumeAccess(null, null); + Mockito.doNothing().when(mockVm).setOwner(null, null); + Mockito.doReturn(null).when(mockVm).listVolumes(null, null, null, 0); + + Whitebox.setInternalState(ksmManager, "volumeManager", mockVm); + doVolumeOps(); + + MetricsRecordBuilder ksmMetrics = getMetrics("KSMMetrics"); + assertCounter("NumVolumeOps", 6L, ksmMetrics); + assertCounter("NumVolumeCreates", 1L, ksmMetrics); + assertCounter("NumVolumeUpdates", 1L, ksmMetrics); + assertCounter("NumVolumeInfos", 1L, ksmMetrics); + assertCounter("NumVolumeCheckAccesses", 1L, ksmMetrics); + assertCounter("NumVolumeDeletes", 1L, ksmMetrics); + assertCounter("NumVolumeLists", 1L, ksmMetrics); + + // inject exception to test for Failure Metrics + Mockito.doThrow(exception).when(mockVm).createVolume(null); + Mockito.doThrow(exception).when(mockVm).deleteVolume(null); + Mockito.doThrow(exception).when(mockVm).getVolumeInfo(null); + Mockito.doThrow(exception).when(mockVm).checkVolumeAccess(null, null); + Mockito.doThrow(exception).when(mockVm).setOwner(null, null); + Mockito.doThrow(exception).when(mockVm).listVolumes(null, null, null, 0); + + Whitebox.setInternalState(ksmManager, "volumeManager", mockVm); + doVolumeOps(); + + ksmMetrics = getMetrics("KSMMetrics"); + assertCounter("NumVolumeOps", 12L, ksmMetrics); + assertCounter("NumVolumeCreates", 2L, ksmMetrics); + assertCounter("NumVolumeUpdates", 2L, ksmMetrics); + assertCounter("NumVolumeInfos", 2L, ksmMetrics); + assertCounter("NumVolumeCheckAccesses", 2L, ksmMetrics); + assertCounter("NumVolumeDeletes", 2L, ksmMetrics); + assertCounter("NumVolumeLists", 2L, ksmMetrics); + + assertCounter("NumVolumeCreateFails", 1L, ksmMetrics); + assertCounter("NumVolumeUpdateFails", 1L, ksmMetrics); + assertCounter("NumVolumeInfoFails", 1L, ksmMetrics); + assertCounter("NumVolumeCheckAccessFails", 1L, ksmMetrics); + assertCounter("NumVolumeDeleteFails", 1L, ksmMetrics); + assertCounter("NumVolumeListFails", 1L, ksmMetrics); + } + + @Test + public void testBucketOps() throws IOException { + BucketManager bucketManager = (BucketManager) Whitebox + .getInternalState(ksmManager, "bucketManager"); + BucketManager mockBm = Mockito.spy(bucketManager); + + Mockito.doNothing().when(mockBm).createBucket(null); + Mockito.doNothing().when(mockBm).deleteBucket(null, null); + Mockito.doReturn(null).when(mockBm).getBucketInfo(null, null); + Mockito.doNothing().when(mockBm).setBucketProperty(null); + Mockito.doReturn(null).when(mockBm).listBuckets(null, null, null, 0); + + Whitebox.setInternalState(ksmManager, "bucketManager", mockBm); + doBucketOps(); + + MetricsRecordBuilder ksmMetrics = getMetrics("KSMMetrics"); + assertCounter("NumBucketOps", 5L, ksmMetrics); + assertCounter("NumBucketCreates", 1L, ksmMetrics); + assertCounter("NumBucketUpdates", 1L, ksmMetrics); + assertCounter("NumBucketInfos", 1L, ksmMetrics); + assertCounter("NumBucketDeletes", 1L, ksmMetrics); + assertCounter("NumBucketLists", 1L, ksmMetrics); + + // inject exception to test for Failure Metrics + Mockito.doThrow(exception).when(mockBm).createBucket(null); + Mockito.doThrow(exception).when(mockBm).deleteBucket(null, null); + Mockito.doThrow(exception).when(mockBm).getBucketInfo(null, null); + Mockito.doThrow(exception).when(mockBm).setBucketProperty(null); + Mockito.doThrow(exception).when(mockBm).listBuckets(null, null, null, 0); + + Whitebox.setInternalState(ksmManager, "bucketManager", mockBm); + doBucketOps(); + + ksmMetrics = getMetrics("KSMMetrics"); + assertCounter("NumBucketOps", 10L, ksmMetrics); + assertCounter("NumBucketCreates", 2L, ksmMetrics); + assertCounter("NumBucketUpdates", 2L, ksmMetrics); + assertCounter("NumBucketInfos", 2L, ksmMetrics); + assertCounter("NumBucketDeletes", 2L, ksmMetrics); + assertCounter("NumBucketLists", 2L, ksmMetrics); + + assertCounter("NumBucketCreateFails", 1L, ksmMetrics); + assertCounter("NumBucketUpdateFails", 1L, ksmMetrics); + assertCounter("NumBucketInfoFails", 1L, ksmMetrics); + assertCounter("NumBucketDeleteFails", 1L, ksmMetrics); + assertCounter("NumBucketListFails", 1L, ksmMetrics); + } + + @Test + public void testKeyOps() throws IOException { + KeyManager bucketManager = (KeyManager) Whitebox + .getInternalState(ksmManager, "keyManager"); + KeyManager mockKm = Mockito.spy(bucketManager); + + Mockito.doReturn(null).when(mockKm).allocateKey(null); + Mockito.doNothing().when(mockKm).deleteKey(null); + Mockito.doReturn(null).when(mockKm).lookupKey(null); + Mockito.doReturn(null).when(mockKm).listKeys(null, null, null, null, 0); + + Whitebox.setInternalState(ksmManager, "keyManager", mockKm); + doKeyOps(); + + MetricsRecordBuilder ksmMetrics = getMetrics("KSMMetrics"); + assertCounter("NumKeyOps", 4L, ksmMetrics); + assertCounter("NumKeyAllocate", 1L, ksmMetrics); + assertCounter("NumKeyLookup", 1L, ksmMetrics); + assertCounter("NumKeyDeletes", 1L, ksmMetrics); + assertCounter("NumKeyLists", 1L, ksmMetrics); + + // inject exception to test for Failure Metrics + Mockito.doThrow(exception).when(mockKm).allocateKey(null); + Mockito.doThrow(exception).when(mockKm).deleteKey(null); + Mockito.doThrow(exception).when(mockKm).lookupKey(null); + Mockito.doThrow(exception).when(mockKm).listKeys( + null, null, null, null, 0); + + Whitebox.setInternalState(ksmManager, "keyManager", mockKm); + doKeyOps(); + + ksmMetrics = getMetrics("KSMMetrics"); + assertCounter("NumKeyOps", 8L, ksmMetrics); + assertCounter("NumKeyAllocate", 2L, ksmMetrics); + assertCounter("NumKeyLookup", 2L, ksmMetrics); + assertCounter("NumKeyDeletes", 2L, ksmMetrics); + assertCounter("NumKeyLists", 2L, ksmMetrics); + + assertCounter("NumKeyAllocateFails", 1L, ksmMetrics); + assertCounter("NumKeyLookupFails", 1L, ksmMetrics); + assertCounter("NumKeyDeleteFails", 1L, ksmMetrics); + assertCounter("NumKeyListFails", 1L, ksmMetrics); + } + + /** + * Test volume operations with ignoring thrown exception. + */ + private void doVolumeOps() { + try { + ksmManager.createVolume(null); + } catch (IOException ignored) { + } + + try { + ksmManager.deleteVolume(null); + } catch (IOException ignored) { + } + + try { + ksmManager.getVolumeInfo(null); + } catch (IOException ignored) { + } + + try { + ksmManager.checkVolumeAccess(null, null); + } catch (IOException ignored) { + } + + try { + ksmManager.setOwner(null, null); + } catch (IOException ignored) { + } + + try { + ksmManager.listAllVolumes(null, null, 0); + } catch (IOException ignored) { + } + } + + /** + * Test bucket operations with ignoring thrown exception. + */ + private void doBucketOps() { + try { + ksmManager.createBucket(null); + } catch (IOException ignored) { + } + + try { + ksmManager.deleteBucket(null, null); + } catch (IOException ignored) { + } + + try { + ksmManager.getBucketInfo(null, null); + } catch (IOException ignored) { + } + + try { + ksmManager.setBucketProperty(null); + } catch (IOException ignored) { + } + + try { + ksmManager.listBuckets(null, null, null, 0); + } catch (IOException ignored) { + } + } + + /** + * Test key operations with ignoring thrown exception. + */ + private void doKeyOps() { + try { + ksmManager.allocateKey(null); + } catch (IOException ignored) { + } + + try { + ksmManager.deleteKey(null); + } catch (IOException ignored) { + } + + try { + ksmManager.lookupKey(null); + } catch (IOException ignored) { + } + + try { + ksmManager.listKeys(null, null, null, null, 0); + } catch (IOException ignored) { + } + } +}