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 com.google.common.collect.Iterables.size;
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertNull;
22  import static org.mockito.Matchers.any;
23  import static org.mockito.Mockito.mock;
24  import static org.mockito.Mockito.when;
25  
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.util.concurrent.atomic.AtomicReference;
29  
30  import org.apache.hadoop.hbase.HRegionInfo;
31  import org.apache.hadoop.hbase.NamespaceDescriptor;
32  import org.apache.hadoop.hbase.TableName;
33  import org.apache.hadoop.hbase.client.Connection;
34  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
35  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
36  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.Quotas;
37  import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceQuota;
38  import org.apache.hadoop.hbase.testclassification.SmallTests;
39  import org.apache.hadoop.hbase.util.Bytes;
40  import org.junit.Before;
41  import org.junit.Test;
42  import org.junit.experimental.categories.Category;
43  import org.mockito.invocation.InvocationOnMock;
44  import org.mockito.stubbing.Answer;
45  
46  /**
47   * Test class for {@link NamespaceQuotaSnapshotStore}.
48   */
49  @Category(SmallTests.class)
50  public class TestNamespaceQuotaViolationStore {
51    private static final long ONE_MEGABYTE = 1024L * 1024L;
52  
53    private Connection conn;
54    private QuotaObserverChore chore;
55    private Map<HRegionInfo, Long> regionReports;
56    private NamespaceQuotaSnapshotStore store;
57  
58    @Before
59    public void setup() {
60      conn = mock(Connection.class);
61      chore = mock(QuotaObserverChore.class);
62      regionReports = new HashMap<>();
63      store = new NamespaceQuotaSnapshotStore(conn, chore, regionReports);
64    }
65    
66    @Test
67    public void testGetSpaceQuota() throws Exception {
68      NamespaceQuotaSnapshotStore mockStore = mock(NamespaceQuotaSnapshotStore.class);
69      when(mockStore.getSpaceQuota(any(String.class))).thenCallRealMethod();
70  
71      Quotas quotaWithSpace = Quotas.newBuilder().setSpace(
72          SpaceQuota.newBuilder()
73              .setSoftLimit(1024L)
74              .setViolationPolicy(QuotaProtos.SpaceViolationPolicy.DISABLE)
75              .build())
76          .build();
77      Quotas quotaWithoutSpace = Quotas.newBuilder().build();
78  
79      final AtomicReference<Quotas> quotaRef = new AtomicReference<>();
80      when(mockStore.getQuotaForNamespace(any(String.class))).then(new Answer<Quotas>() {
81        @Override
82        public Quotas answer(InvocationOnMock invocation) throws Throwable {
83          return quotaRef.get();
84        }
85      });
86  
87      quotaRef.set(quotaWithSpace);
88      assertEquals(quotaWithSpace.getSpace(), mockStore.getSpaceQuota("ns"));
89      quotaRef.set(quotaWithoutSpace);
90      assertNull(mockStore.getSpaceQuota("ns"));
91    }
92  
93    @Test
94    public void testTargetViolationState() {
95      final String NS = "ns";
96      TableName tn1 = TableName.valueOf(NS, "tn1");
97      TableName tn2 = TableName.valueOf(NS, "tn2");
98      TableName tn3 = TableName.valueOf("tn3");
99      SpaceQuota quota = SpaceQuota.newBuilder()
100         .setSoftLimit(ONE_MEGABYTE)
101         .setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(SpaceViolationPolicy.DISABLE))
102         .build();
103 
104     // Create some junk data to filter. Makes sure it's so large that it would
105     // immediately violate the quota.
106     for (int i = 0; i < 3; i++) {
107       regionReports.put(new HRegionInfo(tn3, Bytes.toBytes(i), Bytes.toBytes(i + 1)),
108           5L * ONE_MEGABYTE);
109     }
110 
111     regionReports.put(new HRegionInfo(tn1, Bytes.toBytes(0), Bytes.toBytes(1)), 1024L * 512L);
112     regionReports.put(new HRegionInfo(tn1, Bytes.toBytes(1), Bytes.toBytes(2)), 1024L * 256L);
113 
114     // Below the quota
115     assertEquals(false, store.getTargetState(NS, quota).getQuotaStatus().isInViolation());
116 
117     regionReports.put(new HRegionInfo(tn2, Bytes.toBytes(2), Bytes.toBytes(3)), 1024L * 256L);
118 
119     // Equal to the quota is still in observance
120     assertEquals(false, store.getTargetState(NS, quota).getQuotaStatus().isInViolation());
121 
122     regionReports.put(new HRegionInfo(tn2, Bytes.toBytes(3), Bytes.toBytes(4)), 1024L);
123 
124     // Exceeds the quota, should be in violation
125     assertEquals(true, store.getTargetState(NS, quota).getQuotaStatus().isInViolation());
126     assertEquals(SpaceViolationPolicy.DISABLE, store.getTargetState(NS, quota).getQuotaStatus().getPolicy());
127   }
128 
129   @Test
130   public void testFilterRegionsByNamespace() {
131     TableName tn1 = TableName.valueOf("foo");
132     TableName tn2 = TableName.valueOf("sn", "bar");
133     TableName tn3 = TableName.valueOf("ns", "foo");
134     TableName tn4 = TableName.valueOf("ns", "bar");
135 
136     assertEquals(0, size(store.filterBySubject("asdf")));
137 
138     for (int i = 0; i < 5; i++) {
139       regionReports.put(new HRegionInfo(tn1, Bytes.toBytes(i), Bytes.toBytes(i+1)), 0L);
140     }
141     for (int i = 0; i < 3; i++) {
142       regionReports.put(new HRegionInfo(tn2, Bytes.toBytes(i), Bytes.toBytes(i+1)), 0L);
143     }
144     for (int i = 0; i < 10; i++) {
145       regionReports.put(new HRegionInfo(tn3, Bytes.toBytes(i), Bytes.toBytes(i+1)), 0L);
146     }
147     for (int i = 0; i < 8; i++) {
148       regionReports.put(new HRegionInfo(tn4, Bytes.toBytes(i), Bytes.toBytes(i+1)), 0L);
149     }
150     assertEquals(26, regionReports.size());
151     assertEquals(5, size(store.filterBySubject(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR)));
152     assertEquals(3, size(store.filterBySubject("sn")));
153     assertEquals(18, size(store.filterBySubject("ns")));
154   }
155   
156 }