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  
23  import java.io.IOException;
24  import java.util.List;
25  import java.util.concurrent.atomic.AtomicInteger;
26  
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.CellScannable;
29  import org.apache.hadoop.hbase.CellScanner;
30  import org.apache.hadoop.hbase.HBaseTestingUtility;
31  import org.apache.hadoop.hbase.HConstants;
32  import org.apache.hadoop.hbase.testclassification.MediumTests;
33  import org.apache.hadoop.hbase.TableName;
34  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
35  import org.apache.hadoop.hbase.coprocessor.ProtobufCoprocessorService;
36  import org.apache.hadoop.hbase.ipc.DelegatingPayloadCarryingRpcController;
37  import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
38  import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
39  import org.apache.hadoop.hbase.util.Bytes;
40  import org.junit.AfterClass;
41  import org.junit.BeforeClass;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  
45  import com.google.common.collect.Lists;
46  
47  @Category(MediumTests.class)
48  public class TestRpcControllerFactory {
49  
50    public static class StaticRpcControllerFactory extends RpcControllerFactory {
51  
52      public StaticRpcControllerFactory(Configuration conf) {
53        super(conf);
54      }
55  
56      public PayloadCarryingRpcController newController() {
57        return new CountingRpcController(super.newController());
58      }
59  
60      public PayloadCarryingRpcController newController(final CellScanner cellScanner) {
61        return new CountingRpcController(super.newController(cellScanner));
62      }
63  
64      public PayloadCarryingRpcController newController(final List<CellScannable> cellIterables) {
65        return new CountingRpcController(super.newController(cellIterables));
66      }
67    }
68  
69    public static class CountingRpcController extends DelegatingPayloadCarryingRpcController {
70  
71      private static AtomicInteger INT_PRIORITY = new AtomicInteger();
72      private static AtomicInteger TABLE_PRIORITY = new AtomicInteger();
73  
74      public CountingRpcController(PayloadCarryingRpcController delegate) {
75        super(delegate);
76      }
77  
78      @Override
79      public void setPriority(int priority) {
80        super.setPriority(priority);
81        INT_PRIORITY.incrementAndGet();
82      }
83  
84      @Override
85      public void setPriority(TableName tn) {
86        super.setPriority(tn);
87        // ignore counts for system tables - it could change and we really only want to check on what
88        // the client should change
89        if (!tn.isSystemTable()) {
90          TABLE_PRIORITY.incrementAndGet();
91        }
92  
93      }
94    }
95  
96    private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
97  
98    @BeforeClass
99    public static void setup() throws Exception {
100     // load an endpoint so we have an endpoint to test - it doesn't matter which one, but
101     // this is already in tests, so we can just use it.
102     Configuration conf = UTIL.getConfiguration();
103     conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
104       ProtobufCoprocessorService.class.getName());
105     
106     UTIL.startMiniCluster();
107   }
108 
109   @AfterClass
110   public static void teardown() throws Exception {
111     UTIL.shutdownMiniCluster();
112   }
113 
114   /**
115    * check some of the methods and make sure we are incrementing each time. Its a bit tediuous to
116    * cover all methods here and really is a bit brittle since we can always add new methods but
117    * won't be sure to add them here. So we just can cover the major ones.
118    * @throws Exception on failure
119    */
120   @Test
121   public void testCountController() throws Exception {
122     Configuration conf = new Configuration(UTIL.getConfiguration());
123     // setup our custom controller
124     conf.set(RpcControllerFactory.CUSTOM_CONTROLLER_CONF_KEY,
125       StaticRpcControllerFactory.class.getName());
126 
127     TableName name = TableName.valueOf("testcustomcontroller");
128     UTIL.createTable(name, fam1).close();
129 
130     // change one of the connection properties so we get a new HConnection with our configuration
131     conf.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT + 1);
132 
133     HTable table = new HTable(conf, name);
134     table.setAutoFlushTo(false);
135     byte[] row = Bytes.toBytes("row");
136     Put p = new Put(row);
137     p.add(fam1, fam1, Bytes.toBytes("val0"));
138     table.put(p);
139     table.flushCommits();
140     Integer counter = 1;
141     counter = verifyCount(counter);
142 
143     Delete d = new Delete(row);
144     d.deleteColumn(fam1, fam1);
145     table.delete(d);
146     counter = verifyCount(counter);
147 
148     Put p2 = new Put(row);
149     p2.add(fam1, Bytes.toBytes("qual"), Bytes.toBytes("val1"));
150     table.batch(Lists.newArrayList(p, p2), new Object[2]);
151     // this only goes to a single server, so we don't need to change the count here
152     counter = verifyCount(counter);
153 
154     Append append = new Append(row);
155     append.add(fam1, fam1, Bytes.toBytes("val2"));
156     table.append(append);
157     counter = verifyCount(counter);
158 
159     // and check the major lookup calls as well
160     Get g = new Get(row);
161     table.get(g);
162     counter = verifyCount(counter);
163 
164     ResultScanner scan = table.getScanner(fam1);
165     scan.next();
166     scan.close();
167     counter = verifyCount(counter);
168 
169     Get g2 = new Get(row);
170     table.get(Lists.newArrayList(g, g2));
171     // same server, so same as above for not changing count
172     counter = verifyCount(counter);
173 
174     // make sure all the scanner types are covered
175     Scan scanInfo = new Scan(row);
176     // regular small
177     scanInfo.setSmall(true);
178     counter = doScan(table, scanInfo, counter);
179 
180     // reversed, small
181     scanInfo.setReversed(true);
182     counter = doScan(table, scanInfo, counter);
183 
184     // reversed, regular
185     scanInfo.setSmall(false);
186     counter = doScan(table, scanInfo, counter);
187 
188     table.close();
189   }
190 
191   int doScan(HTable table, Scan scan, int expectedCount) throws IOException {
192     ResultScanner results = table.getScanner(scan);
193     results.next();
194     results.close();
195     return verifyCount(expectedCount);
196   }
197 
198   int verifyCount(Integer counter) {
199     assertEquals(counter.intValue(), CountingRpcController.TABLE_PRIORITY.get());
200     assertEquals(0, CountingRpcController.INT_PRIORITY.get());
201     return counter + 1;
202   }
203 }