View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.hadoop.hbase.quotas;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertNull;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.util.List;
27  import java.util.concurrent.TimeUnit;
28  
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
31  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
32  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
33  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
34  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceLimitRequest;
35  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceQuota;
36  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Throttle;
37  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.TimedQuota;
38  import org.apache.hadoop.hbase.testclassification.SmallTests;
39  import org.junit.Test;
40  import org.junit.experimental.categories.Category;
41  
42  /**
43   * Test class for {@link QuotaSettingsFactory}.
44   */
45  @Category(SmallTests.class)
46  public class TestQuotaSettingsFactory {
47  
48    @Test
49    public void testAllQuotasAddedToList() {
50      final SpaceQuota spaceQuota = SpaceQuota.newBuilder()
51          .setSoftLimit(1024L * 1024L * 1024L * 50L) // 50G
52          .setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE) // Disable the table
53          .build();
54      final long readLimit = 1000;
55      final long writeLimit = 500;
56      final Throttle throttle = Throttle.newBuilder()
57          // 1000 read reqs/min
58          .setReadNum(TimedQuota.newBuilder().setSoftLimit(readLimit).setTimeUnit(HBaseProtos.TimeUnit.MINUTES).build())
59          // 500 write reqs/min
60          .setWriteNum(TimedQuota.newBuilder().setSoftLimit(writeLimit).setTimeUnit(HBaseProtos.TimeUnit.MINUTES).build())
61          .build();
62      final Quotas quotas = Quotas.newBuilder()
63          .setSpace(spaceQuota) // Set the FS quotas
64          .setThrottle(throttle) // Set some RPC limits
65          .build();
66      final TableName tn = TableName.valueOf("my_table");
67      List<QuotaSettings> settings = QuotaSettingsFactory.fromTableQuotas(tn, quotas);
68      assertEquals(3, settings.size());
69      boolean seenRead = false;
70      boolean seenWrite = false;
71      boolean seenSpace = false;
72      for (QuotaSettings setting : settings) {
73        if (setting instanceof ThrottleSettings) {
74          ThrottleSettings throttleSettings = (ThrottleSettings) setting;
75          switch (throttleSettings.getThrottleType()) {
76            case READ_NUMBER:
77              assertFalse("Should not have multiple read quotas", seenRead);
78              assertEquals(readLimit, throttleSettings.getSoftLimit());
79              assertEquals(TimeUnit.MINUTES, throttleSettings.getTimeUnit());
80              assertEquals(tn, throttleSettings.getTableName());
81              assertNull("Username should be null", throttleSettings.getUserName());
82              assertNull("Namespace should be null", throttleSettings.getNamespace());
83              seenRead = true;
84              break;
85            case WRITE_NUMBER:
86              assertFalse("Should not have multiple write quotas", seenWrite);
87              assertEquals(writeLimit, throttleSettings.getSoftLimit());
88              assertEquals(TimeUnit.MINUTES, throttleSettings.getTimeUnit());
89              assertEquals(tn, throttleSettings.getTableName());
90              assertNull("Username should be null", throttleSettings.getUserName());
91              assertNull("Namespace should be null", throttleSettings.getNamespace());
92              seenWrite = true;
93              break;
94            default:
95              fail("Unexpected throttle type: " + throttleSettings.getThrottleType());
96          }
97        } else if (setting instanceof SpaceLimitSettings) {
98          assertFalse("Should not have multiple space quotas", seenSpace);
99          SpaceLimitSettings spaceLimit = (SpaceLimitSettings) setting;
100         assertEquals(tn, spaceLimit.getTableName());
101         assertNull("Username should be null", spaceLimit.getUserName());
102         assertNull("Namespace should be null", spaceLimit.getNamespace());
103         assertTrue("SpaceLimitSettings should have a SpaceQuota", spaceLimit.getProto().hasQuota());
104         assertEquals(spaceQuota, spaceLimit.getProto().getQuota());
105         seenSpace = true;
106       } else {
107         fail("Unexpected QuotaSettings implementation: " + setting.getClass());
108       }
109     }
110     assertTrue("Should have seen a read quota", seenRead);
111     assertTrue("Should have seen a write quota", seenWrite);
112     assertTrue("Should have seen a space quota", seenSpace);
113   }
114 
115   @Test(expected = IllegalArgumentException.class)
116   public void testNeitherTableNorNamespace() {
117     final SpaceQuota spaceQuota = SpaceQuota.newBuilder()
118         .setSoftLimit(1L)
119         .setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE)
120         .build();
121     QuotaSettingsFactory.fromSpace(null, null, spaceQuota);
122   }
123 
124   @Test(expected = IllegalArgumentException.class)
125   public void testBothTableAndNamespace() {
126     final SpaceQuota spaceQuota = SpaceQuota.newBuilder()
127         .setSoftLimit(1L)
128         .setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE)
129         .build();
130     QuotaSettingsFactory.fromSpace(TableName.valueOf("foo"), "bar", spaceQuota);
131   }
132 
133   @Test
134   public void testSpaceLimitSettings() {
135     final TableName tableName = TableName.valueOf("foo");
136     final long sizeLimit = 1024L * 1024L * 1024L * 75; // 75GB
137     final SpaceViolationPolicy violationPolicy = SpaceViolationPolicy.NO_INSERTS;
138     QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(tableName, sizeLimit, violationPolicy);
139     assertNotNull("QuotaSettings should not be null", settings);
140     assertTrue("Should be an instance of SpaceLimitSettings", settings instanceof SpaceLimitSettings);
141     SpaceLimitSettings spaceLimitSettings = (SpaceLimitSettings) settings;
142     SpaceLimitRequest protoRequest = spaceLimitSettings.getProto();
143     assertTrue("Request should have a SpaceQuota", protoRequest.hasQuota());
144     SpaceQuota quota = protoRequest.getQuota();
145     assertEquals(sizeLimit, quota.getSoftLimit());
146     assertEquals(violationPolicy, ProtobufUtil.toViolationPolicy(quota.getViolationPolicy()));
147     assertFalse("The remove attribute should be false", quota.getRemove());
148   }
149 
150   @Test
151   public void testSpaceLimitSettingsForDeletes() {
152     final String ns = "ns1";
153     final TableName tn = TableName.valueOf("tn1");
154     QuotaSettings nsSettings = QuotaSettingsFactory.removeNamespaceSpaceLimit(ns);
155     assertNotNull("QuotaSettings should not be null", nsSettings);
156     assertTrue("Should be an instance of SpaceLimitSettings", nsSettings instanceof SpaceLimitSettings);
157     SpaceLimitRequest nsProto = ((SpaceLimitSettings) nsSettings).getProto();
158     assertTrue("Request should have a SpaceQuota", nsProto.hasQuota());
159     assertTrue("The remove attribute should be true", nsProto.getQuota().getRemove());
160 
161     QuotaSettings tableSettings = QuotaSettingsFactory.removeTableSpaceLimit(tn);
162     assertNotNull("QuotaSettings should not be null", tableSettings);
163     assertTrue("Should be an instance of SpaceLimitSettings", tableSettings instanceof SpaceLimitSettings);
164     SpaceLimitRequest tableProto = ((SpaceLimitSettings) tableSettings).getProto();
165     assertTrue("Request should have a SpaceQuota", tableProto.hasQuota());
166     assertTrue("The remove attribute should be true", tableProto.getQuota().getRemove());
167    }
168 }