View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client;
19  
20  import static org.apache.hadoop.hbase.HBaseTestingUtility.fam1;
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertTrue;
24  
25  import com.google.common.collect.ConcurrentHashMultiset;
26  import com.google.common.collect.Lists;
27  
28  import java.io.IOException;
29  import java.util.List;
30  import java.util.concurrent.atomic.AtomicInteger;
31  
32  import com.google.common.collect.Multiset;
33  import org.apache.hadoop.conf.Configuration;
34  import org.apache.hadoop.hbase.CellScannable;
35  import org.apache.hadoop.hbase.CellScanner;
36  import org.apache.hadoop.hbase.HBaseTestingUtility;
37  import org.apache.hadoop.hbase.HConstants;
38  import org.apache.hadoop.hbase.TableName;
39  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
40  import org.apache.hadoop.hbase.coprocessor.ProtobufCoprocessorService;
41  import org.apache.hadoop.hbase.ipc.DelegatingHBaseRpcController;
42  import org.apache.hadoop.hbase.ipc.HBaseRpcController;
43  import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
44  import org.apache.hadoop.hbase.testclassification.MediumTests;
45  import org.apache.hadoop.hbase.util.Bytes;
46  import org.junit.AfterClass;
47  import org.junit.BeforeClass;
48  import org.junit.Test;
49  import org.junit.experimental.categories.Category;
50  
51  @Category(MediumTests.class)
52  public class TestRpcControllerFactory {
53  
54    public static class StaticRpcControllerFactory extends RpcControllerFactory {
55  
56      public StaticRpcControllerFactory(Configuration conf) {
57        super(conf);
58      }
59  
60      @Override
61      public HBaseRpcController newController() {
62        return new CountingRpcController(super.newController());
63      }
64  
65      @Override
66      public HBaseRpcController newController(final CellScanner cellScanner) {
67        return new CountingRpcController(super.newController(cellScanner));
68      }
69  
70      @Override
71      public HBaseRpcController newController(final List<CellScannable> cellIterables) {
72        return new CountingRpcController(super.newController(cellIterables));
73      }
74    }
75  
76    public static class CountingRpcController extends DelegatingHBaseRpcController {
77  
78      private static Multiset<Integer> GROUPED_PRIORITY = ConcurrentHashMultiset.create();
79      private static AtomicInteger INT_PRIORITY = new AtomicInteger();
80      private static AtomicInteger TABLE_PRIORITY = new AtomicInteger();
81  
82      public CountingRpcController(HBaseRpcController delegate) {
83        super(delegate);
84      }
85  
86      @Override
87      public void setPriority(int priority) {
88        int oldPriority = getPriority();
89        super.setPriority(priority);
90        int newPriority = getPriority();
91        if (newPriority != oldPriority) {
92          INT_PRIORITY.incrementAndGet();
93          GROUPED_PRIORITY.add(priority);
94        }
95      }
96  
97      @Override
98      public void setPriority(TableName tn) {
99        super.setPriority(tn);
100       // ignore counts for system tables - it could change and we really only want to check on what
101       // the client should change
102       if (tn != null && !tn.isSystemTable()) {
103         TABLE_PRIORITY.incrementAndGet();
104       }
105 
106     }
107   }
108 
109   private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
110 
111   @BeforeClass
112   public static void setup() throws Exception {
113     // load an endpoint so we have an endpoint to test - it doesn't matter which one, but
114     // this is already in tests, so we can just use it.
115     Configuration conf = UTIL.getConfiguration();
116     conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
117       ProtobufCoprocessorService.class.getName());
118 
119     UTIL.startMiniCluster();
120   }
121 
122   @AfterClass
123   public static void teardown() throws Exception {
124     UTIL.shutdownMiniCluster();
125   }
126 
127   /**
128    * check some of the methods and make sure we are incrementing each time. Its a bit tediuous to
129    * cover all methods here and really is a bit brittle since we can always add new methods but
130    * won't be sure to add them here. So we just can cover the major ones.
131    * @throws Exception on failure
132    */
133   @Test
134   public void testCountController() throws Exception {
135     Configuration conf = new Configuration(UTIL.getConfiguration());
136     // setup our custom controller
137     conf.set(RpcControllerFactory.CUSTOM_CONTROLLER_CONF_KEY,
138       StaticRpcControllerFactory.class.getName());
139 
140     TableName name = TableName.valueOf("testcustomcontroller");
141     UTIL.createTable(name, fam1).close();
142 
143     // change one of the connection properties so we get a new HConnection with our configuration
144     conf.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT + 1);
145 
146     Connection connection = ConnectionFactory.createConnection(conf);
147     Table table = connection.getTable(name);
148     byte[] row = Bytes.toBytes("row");
149     Put p = new Put(row);
150     p.add(fam1, fam1, Bytes.toBytes("val0"));
151     table.put(p);
152 
153     Integer counter = 1;
154     counter = verifyCount(counter);
155 
156     Delete d = new Delete(row);
157     d.addColumn(fam1, fam1);
158     table.delete(d);
159     counter = verifyCount(counter);
160 
161     Put p2 = new Put(row);
162     p2.add(fam1, Bytes.toBytes("qual"), Bytes.toBytes("val1"));
163     table.batch(Lists.newArrayList(p, p2), new Object[2]);
164     // this only goes to a single server, so we don't need to change the count here
165     counter = verifyCount(counter);
166 
167     Append append = new Append(row);
168     append.add(fam1, fam1, Bytes.toBytes("val2"));
169     table.append(append);
170     counter = verifyCount(counter);
171 
172     // and check the major lookup calls as well
173     Get g = new Get(row);
174     table.get(g);
175     counter = verifyCount(counter);
176 
177     ResultScanner scan = table.getScanner(fam1);
178     scan.next();
179     scan.close();
180     counter = verifyCount(counter);
181 
182     Get g2 = new Get(row);
183     table.get(Lists.newArrayList(g, g2));
184     // same server, so same as above for not changing count
185     counter = verifyCount(counter);
186 
187     // make sure all the scanner types are covered
188     Scan scanInfo = new Scan(row);
189     // regular small
190     scanInfo.setSmall(true);
191     counter = doScan(table, scanInfo, counter);
192 
193     // reversed, small
194     scanInfo.setReversed(true);
195     counter = doScan(table, scanInfo, counter);
196 
197     // reversed, regular
198     scanInfo.setSmall(false);
199     counter = doScan(table, scanInfo, counter);
200 
201     // make sure we have no priority count
202     verifyPriorityGroupCount(HConstants.ADMIN_QOS, 0);
203     // lets set a custom priority on a get
204     Get get = new Get(row);
205     get.setPriority(HConstants.ADMIN_QOS);
206     table.get(get);
207     verifyPriorityGroupCount(HConstants.ADMIN_QOS, 1);
208 
209     table.close();
210   }
211 
212   int doScan(Table table, Scan scan, int expectedCount) throws IOException {
213     ResultScanner results = table.getScanner(scan);
214     results.next();
215     results.close();
216     return verifyCount(expectedCount);
217   }
218 
219   int verifyCount(Integer counter) {
220     assertTrue(CountingRpcController.TABLE_PRIORITY.get() >= counter);
221     assertEquals(0, CountingRpcController.INT_PRIORITY.get());
222     return CountingRpcController.TABLE_PRIORITY.get() + 1;
223   }
224 
225   void verifyPriorityGroupCount(int priorityLevel, int count) {
226     assertEquals(count, CountingRpcController.GROUPED_PRIORITY.count(priorityLevel));
227   }
228 
229   @Test
230   public void testFallbackToDefaultRpcControllerFactory() {
231     Configuration conf = new Configuration(UTIL.getConfiguration());
232     conf.set(RpcControllerFactory.CUSTOM_CONTROLLER_CONF_KEY, "foo.bar.Baz");
233 
234     // Should not fail
235     RpcControllerFactory factory = RpcControllerFactory.instantiate(conf);
236     assertNotNull(factory);
237     assertEquals(factory.getClass(), RpcControllerFactory.class);
238   }
239 }