001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.quotas;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import org.apache.hadoop.hbase.HBaseClassTestRule;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.testclassification.SmallTests;
027import org.junit.ClassRule;
028import org.junit.Test;
029import org.junit.experimental.categories.Category;
030
031import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
032import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos;
033
034@Category(SmallTests.class)
035public class TestGlobalQuotaSettingsImpl {
036
037  @ClassRule
038  public static final HBaseClassTestRule CLASS_RULE =
039      HBaseClassTestRule.forClass(TestGlobalQuotaSettingsImpl.class);
040
041  QuotaProtos.TimedQuota REQUEST_THROTTLE = QuotaProtos.TimedQuota.newBuilder()
042      .setScope(QuotaProtos.QuotaScope.MACHINE).setSoftLimit(100)
043      .setTimeUnit(HBaseProtos.TimeUnit.MINUTES).build();
044  QuotaProtos.Throttle THROTTLE = QuotaProtos.Throttle.newBuilder()
045      .setReqNum(REQUEST_THROTTLE).build();
046
047  QuotaProtos.SpaceQuota SPACE_QUOTA = QuotaProtos.SpaceQuota.newBuilder()
048      .setSoftLimit(1024L * 1024L).setViolationPolicy(QuotaProtos.SpaceViolationPolicy.NO_WRITES)
049      .build();
050
051  @Test
052  public void testMergeThrottle() throws IOException {
053    QuotaProtos.Quotas quota = QuotaProtos.Quotas.newBuilder()
054        .setThrottle(THROTTLE).build();
055    QuotaProtos.TimedQuota writeQuota = REQUEST_THROTTLE.toBuilder()
056        .setSoftLimit(500).build();
057    // Unset the req throttle, set a write throttle
058    QuotaProtos.ThrottleRequest writeThrottle = QuotaProtos.ThrottleRequest.newBuilder()
059        .setTimedQuota(writeQuota).setType(QuotaProtos.ThrottleType.WRITE_NUMBER).build();
060
061    GlobalQuotaSettingsImpl settings = new GlobalQuotaSettingsImpl("joe", null, null, null, quota);
062    GlobalQuotaSettingsImpl merged = settings.merge(
063      new ThrottleSettings("joe", null, null, null, writeThrottle));
064
065    QuotaProtos.Throttle mergedThrottle = merged.getThrottleProto();
066    // Verify the request throttle is in place
067    assertTrue(mergedThrottle.hasReqNum());
068    QuotaProtos.TimedQuota actualReqNum = mergedThrottle.getReqNum();
069    assertEquals(REQUEST_THROTTLE.getSoftLimit(), actualReqNum.getSoftLimit());
070
071    // Verify the write throttle is in place
072    assertTrue(mergedThrottle.hasWriteNum());
073    QuotaProtos.TimedQuota actualWriteNum = mergedThrottle.getWriteNum();
074    assertEquals(writeQuota.getSoftLimit(), actualWriteNum.getSoftLimit());
075  }
076
077  @Test
078  public void testMergeSpace() throws IOException {
079    TableName tn = TableName.valueOf("foo");
080    QuotaProtos.Quotas quota = QuotaProtos.Quotas.newBuilder()
081        .setSpace(SPACE_QUOTA).build();
082
083    GlobalQuotaSettingsImpl settings = new GlobalQuotaSettingsImpl(null, tn, null, null, quota);
084    // Switch the violation policy to DISABLE
085    GlobalQuotaSettingsImpl merged = settings.merge(
086        new SpaceLimitSettings(tn, SPACE_QUOTA.getSoftLimit(), SpaceViolationPolicy.DISABLE));
087
088    QuotaProtos.SpaceQuota mergedSpaceQuota = merged.getSpaceProto();
089    assertEquals(SPACE_QUOTA.getSoftLimit(), mergedSpaceQuota.getSoftLimit());
090    assertEquals(
091        QuotaProtos.SpaceViolationPolicy.DISABLE, mergedSpaceQuota.getViolationPolicy());
092  }
093
094  @Test
095  public void testMergeThrottleAndSpace() throws IOException {
096    final String ns = "org1";
097    QuotaProtos.Quotas quota = QuotaProtos.Quotas.newBuilder()
098        .setThrottle(THROTTLE).setSpace(SPACE_QUOTA).build();
099    GlobalQuotaSettingsImpl settings = new GlobalQuotaSettingsImpl(null, null, ns, null, quota);
100
101    QuotaProtos.TimedQuota writeQuota = REQUEST_THROTTLE.toBuilder()
102        .setSoftLimit(500).build();
103    // Add a write throttle
104    QuotaProtos.ThrottleRequest writeThrottle = QuotaProtos.ThrottleRequest.newBuilder()
105        .setTimedQuota(writeQuota).setType(QuotaProtos.ThrottleType.WRITE_NUMBER).build();
106
107    GlobalQuotaSettingsImpl merged = settings.merge(
108      new ThrottleSettings(null, null, ns, null, writeThrottle));
109    GlobalQuotaSettingsImpl finalQuota = merged.merge(new SpaceLimitSettings(
110        ns, SPACE_QUOTA.getSoftLimit(), SpaceViolationPolicy.NO_WRITES_COMPACTIONS));
111
112    // Verify both throttle quotas
113    QuotaProtos.Throttle throttle = finalQuota.getThrottleProto();
114    assertTrue(throttle.hasReqNum());
115    QuotaProtos.TimedQuota reqNumQuota = throttle.getReqNum();
116    assertEquals(REQUEST_THROTTLE.getSoftLimit(), reqNumQuota.getSoftLimit());
117
118    assertTrue(throttle.hasWriteNum());
119    QuotaProtos.TimedQuota writeNumQuota = throttle.getWriteNum();
120    assertEquals(writeQuota.getSoftLimit(), writeNumQuota.getSoftLimit());
121
122    // Verify space quota
123    QuotaProtos.SpaceQuota finalSpaceQuota = finalQuota.getSpaceProto();
124    assertEquals(SPACE_QUOTA.getSoftLimit(), finalSpaceQuota.getSoftLimit());
125    assertEquals(
126        QuotaProtos.SpaceViolationPolicy.NO_WRITES_COMPACTIONS,
127        finalSpaceQuota.getViolationPolicy());
128  }
129}