View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.thrift2;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.hbase.DoNotRetryIOException;
25  import org.apache.hadoop.hbase.HBaseTestingUtility;
26  import org.apache.hadoop.hbase.HColumnDescriptor;
27  import org.apache.hadoop.hbase.HTableDescriptor;
28  import org.apache.hadoop.hbase.TableName;
29  import org.apache.hadoop.hbase.client.Admin;
30  import org.apache.hadoop.hbase.security.UserProvider;
31  import org.apache.hadoop.hbase.testclassification.ClientTests;
32  import org.apache.hadoop.hbase.testclassification.MediumTests;
33  import org.apache.hadoop.hbase.thrift2.generated.TAppend;
34  import org.apache.hadoop.hbase.thrift2.generated.TColumnIncrement;
35  import org.apache.hadoop.hbase.thrift2.generated.TColumnValue;
36  import org.apache.hadoop.hbase.thrift2.generated.TCompareOp;
37  import org.apache.hadoop.hbase.thrift2.generated.TDelete;
38  import org.apache.hadoop.hbase.thrift2.generated.TGet;
39  import org.apache.hadoop.hbase.thrift2.generated.TIOError;
40  import org.apache.hadoop.hbase.thrift2.generated.TIncrement;
41  import org.apache.hadoop.hbase.thrift2.generated.TMutation;
42  import org.apache.hadoop.hbase.thrift2.generated.TPut;
43  import org.apache.hadoop.hbase.thrift2.generated.TRowMutations;
44  import org.apache.hadoop.hbase.thrift2.generated.TScan;
45  import org.apache.hadoop.hbase.util.Bytes;
46  import org.apache.thrift.TException;
47  import org.junit.AfterClass;
48  import org.junit.Before;
49  import org.junit.BeforeClass;
50  import org.junit.Test;
51  import org.junit.experimental.categories.Category;
52  
53  import java.io.IOException;
54  import java.nio.ByteBuffer;
55  import java.util.ArrayList;
56  import java.util.Arrays;
57  import java.util.List;
58  
59  import static java.nio.ByteBuffer.wrap;
60  import static org.junit.Assert.assertEquals;
61  import static org.junit.Assert.assertFalse;
62  import static org.junit.Assert.assertTrue;
63  
64  @Category({ClientTests.class, MediumTests.class})
65  public class TestThriftHBaseServiceHandlerWithReadOnly {
66  
67    private static final Log LOG = LogFactory.getLog(TestThriftHBaseServiceHandlerWithReadOnly.class);
68    private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
69  
70    // Static names for tables, columns, rows, and values
71    private static byte[] tableAname = Bytes.toBytes("tableA");
72    private static byte[] familyAname = Bytes.toBytes("familyA");
73    private static byte[] familyBname = Bytes.toBytes("familyB");
74    private static byte[] qualifierAname = Bytes.toBytes("qualifierA");
75    private static byte[] qualifierBname = Bytes.toBytes("qualifierB");
76    private static byte[] valueAname = Bytes.toBytes("valueA");
77    private static byte[] valueBname = Bytes.toBytes("valueB");
78    private static HColumnDescriptor[] families = new HColumnDescriptor[] {
79        new HColumnDescriptor(familyAname).setMaxVersions(3),
80        new HColumnDescriptor(familyBname).setMaxVersions(2)
81    };
82  
83    @BeforeClass
84    public static void beforeClass() throws Exception {
85      UTIL.getConfiguration().setBoolean("hbase.thrift.readonly", true);
86      UTIL.getConfiguration().set("hbase.client.retries.number", "3");
87      UTIL.startMiniCluster();
88      Admin admin = UTIL.getHBaseAdmin();
89      HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableAname));
90      for (HColumnDescriptor family : families) {
91        tableDescriptor.addFamily(family);
92      }
93      admin.createTable(tableDescriptor);
94      admin.close();
95    }
96  
97    @AfterClass
98    public static void afterClass() throws Exception {
99      UTIL.shutdownMiniCluster();
100   }
101 
102   @Before
103   public void setup() throws Exception {
104 
105   }
106 
107   private ThriftHBaseServiceHandler createHandler() throws TException {
108     try {
109       Configuration conf = UTIL.getConfiguration();
110       return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf));
111     } catch (IOException ie) {
112       throw new TException(ie);
113     }
114   }
115 
116   @Test
117   public void testExistsWithReadOnly() throws TException {
118 
119     ThriftHBaseServiceHandler handler = createHandler();
120     byte[] rowName = "testExists".getBytes();
121     ByteBuffer table = wrap(tableAname);
122     TGet get = new TGet(wrap(rowName));
123 
124     boolean exceptionCaught = false;
125     try {
126       handler.exists(table, get);
127     } catch (TIOError e) {
128       exceptionCaught = true;
129     } finally {
130       assertFalse(exceptionCaught);
131     }
132   }
133 
134   @Test
135   public void testExistsAllWithReadOnly() throws TException {
136     ThriftHBaseServiceHandler handler = createHandler();
137     byte[] rowName1 = "testExistsAll1".getBytes();
138     byte[] rowName2 = "testExistsAll2".getBytes();
139     ByteBuffer table = wrap(tableAname);
140 
141     List<TGet> gets = new ArrayList<>();
142     gets.add(new TGet(wrap(rowName1)));
143     gets.add(new TGet(wrap(rowName2)));
144 
145     boolean exceptionCaught = false;
146     try {
147       handler.existsAll(table, gets);
148     } catch (TIOError e) {
149       exceptionCaught = true;
150     } finally {
151       assertFalse(exceptionCaught);
152     }
153   }
154 
155   @Test
156   public void testGetWithReadOnly() throws Exception {
157     ThriftHBaseServiceHandler handler = createHandler();
158     byte[] rowName = "testGet".getBytes();
159     ByteBuffer table = wrap(tableAname);
160 
161     TGet get = new TGet(wrap(rowName));
162 
163     boolean exceptionCaught = false;
164     try {
165       handler.get(table, get);
166     } catch (TIOError e) {
167       exceptionCaught = true;
168     } finally {
169       assertFalse(exceptionCaught);
170     }
171   }
172 
173   @Test
174   public void testGetMultipleWithReadOnly() throws Exception {
175     ThriftHBaseServiceHandler handler = createHandler();
176     ByteBuffer table = wrap(tableAname);
177     byte[] rowName1 = "testGetMultiple1".getBytes();
178     byte[] rowName2 = "testGetMultiple2".getBytes();
179 
180     List<TGet> gets = new ArrayList<>(2);
181     gets.add(new TGet(wrap(rowName1)));
182     gets.add(new TGet(wrap(rowName2)));
183 
184     boolean exceptionCaught = false;
185     try {
186       handler.getMultiple(table, gets);
187     } catch (TIOError e) {
188       exceptionCaught = true;
189     } finally {
190       assertFalse(exceptionCaught);
191     }
192   }
193 
194   @Test
195   public void testPutWithReadOnly() throws Exception {
196     ThriftHBaseServiceHandler handler = createHandler();
197     ByteBuffer table = wrap(tableAname);
198     byte[] rowName = "testPut".getBytes();
199 
200     List<TColumnValue> columnValues = new ArrayList<>(2);
201     columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)));
202     columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)));
203     TPut put = new TPut(wrap(rowName), columnValues);
204 
205     boolean exceptionCaught = false;
206     try {
207       handler.put(table, put);
208     } catch (TIOError e) {
209       exceptionCaught = true;
210       assertTrue(e.getCause() instanceof DoNotRetryIOException);
211       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
212     } finally {
213       assertTrue(exceptionCaught);
214     }
215   }
216 
217   @Test
218   public void testCheckAndPutWithReadOnly() throws Exception {
219     ThriftHBaseServiceHandler handler = createHandler();
220     byte[] rowName = "testCheckAndPut".getBytes();
221     ByteBuffer table = wrap(tableAname);
222 
223     List<TColumnValue> columnValuesA = new ArrayList<>(1);
224     TColumnValue columnValueA = new TColumnValue(wrap(familyAname), wrap(qualifierAname),
225         wrap(valueAname));
226     columnValuesA.add(columnValueA);
227     TPut putA = new TPut(wrap(rowName), columnValuesA);
228     putA.setColumnValues(columnValuesA);
229 
230     List<TColumnValue> columnValuesB = new ArrayList<>(1);
231     TColumnValue columnValueB = new TColumnValue(wrap(familyBname), wrap(qualifierBname),
232         wrap(valueBname));
233     columnValuesB.add(columnValueB);
234     TPut putB = new TPut(wrap(rowName), columnValuesB);
235     putB.setColumnValues(columnValuesB);
236 
237     boolean exceptionCaught = false;
238     try {
239       handler.checkAndPut(table, wrap(rowName), wrap(familyAname),
240           wrap(qualifierAname), wrap(valueAname), putB);
241     } catch (TIOError e) {
242       exceptionCaught = true;
243       assertTrue(e.getCause() instanceof DoNotRetryIOException);
244       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
245     } finally {
246       assertTrue(exceptionCaught);
247     }
248   }
249 
250   @Test
251   public void testPutMultipleWithReadOnly() throws Exception {
252     ThriftHBaseServiceHandler handler = createHandler();
253     ByteBuffer table = wrap(tableAname);
254     byte[] rowName1 = "testPutMultiple1".getBytes();
255     byte[] rowName2 = "testPutMultiple2".getBytes();
256 
257     List<TColumnValue> columnValues = new ArrayList<>(2);
258     columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)));
259     columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)));
260     List<TPut> puts = new ArrayList<>(2);
261     puts.add(new TPut(wrap(rowName1), columnValues));
262     puts.add(new TPut(wrap(rowName2), columnValues));
263 
264     boolean exceptionCaught = false;
265     try {
266       handler.putMultiple(table, puts);
267     } catch (TIOError e) {
268       exceptionCaught = true;
269       assertTrue(e.getCause() instanceof DoNotRetryIOException);
270       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
271     } finally {
272       assertTrue(exceptionCaught);
273     }
274   }
275 
276   @Test
277   public void testDeleteWithReadOnly() throws Exception {
278     ThriftHBaseServiceHandler handler = createHandler();
279     byte[] rowName = "testDelete".getBytes();
280     ByteBuffer table = wrap(tableAname);
281 
282     TDelete delete = new TDelete(wrap(rowName));
283 
284     boolean exceptionCaught = false;
285     try {
286       handler.deleteSingle(table, delete);
287     } catch (TIOError e) {
288       exceptionCaught = true;
289       assertTrue(e.getCause() instanceof DoNotRetryIOException);
290       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
291     } finally {
292       assertTrue(exceptionCaught);
293     }
294   }
295 
296   @Test
297   public void testDeleteMultipleWithReadOnly() throws Exception {
298     ThriftHBaseServiceHandler handler = createHandler();
299     ByteBuffer table = wrap(tableAname);
300     byte[] rowName1 = "testDeleteMultiple1".getBytes();
301     byte[] rowName2 = "testDeleteMultiple2".getBytes();
302 
303     List<TDelete> deletes = new ArrayList<>(2);
304     deletes.add(new TDelete(wrap(rowName1)));
305     deletes.add(new TDelete(wrap(rowName2)));
306 
307     boolean exceptionCaught = false;
308     try {
309       handler.deleteMultiple(table, deletes);
310     } catch (TIOError e) {
311       exceptionCaught = true;
312       assertTrue(e.getCause() instanceof DoNotRetryIOException);
313       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
314     } finally {
315       assertTrue(exceptionCaught);
316     }
317   }
318 
319   @Test
320   public void testCheckAndMutateWithReadOnly() throws Exception {
321     ThriftHBaseServiceHandler handler = createHandler();
322     ByteBuffer table = wrap(tableAname);
323     ByteBuffer row = wrap("row".getBytes());
324     ByteBuffer family = wrap(familyAname);
325     ByteBuffer qualifier = wrap(qualifierAname);
326     ByteBuffer value = wrap(valueAname);
327 
328     List<TColumnValue> columnValuesB = new ArrayList<>(1);
329     TColumnValue columnValueB = new TColumnValue(family, wrap(qualifierBname), wrap(valueBname));
330     columnValuesB.add(columnValueB);
331     TPut putB = new TPut(row, columnValuesB);
332     putB.setColumnValues(columnValuesB);
333 
334     TRowMutations tRowMutations = new TRowMutations(row,
335         Arrays.<TMutation> asList(TMutation.put(putB)));
336 
337     boolean exceptionCaught = false;
338     try {
339       handler.checkAndMutate(table, row, family, qualifier, TCompareOp.EQUAL, value,
340           tRowMutations);
341     } catch (TIOError e) {
342       exceptionCaught = true;
343       assertTrue(e.getCause() instanceof DoNotRetryIOException);
344       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
345     } finally {
346       assertTrue(exceptionCaught);
347     }
348   }
349 
350   @Test
351   public void testCheckAndDeleteWithReadOnly() throws Exception {
352     ThriftHBaseServiceHandler handler = createHandler();
353     byte[] rowName = "testCheckAndDelete".getBytes();
354     ByteBuffer table = wrap(tableAname);
355 
356     TDelete delete = new TDelete(wrap(rowName));
357 
358     boolean exceptionCaught = false;
359     try {
360       handler.checkAndDelete(table, wrap(rowName), wrap(familyAname),
361           wrap(qualifierAname), wrap(valueAname), delete);
362     } catch (TIOError e) {
363       exceptionCaught = true;
364       assertTrue(e.getCause() instanceof DoNotRetryIOException);
365       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
366     } finally {
367       assertTrue(exceptionCaught);
368     }
369   }
370 
371   @Test
372   public void testIncrementWithReadOnly() throws Exception {
373     ThriftHBaseServiceHandler handler = createHandler();
374     byte[] rowName = "testIncrement".getBytes();
375     ByteBuffer table = wrap(tableAname);
376 
377     List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
378     incrementColumns.add(new TColumnIncrement(wrap(familyAname), wrap(qualifierAname)));
379     TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
380 
381     boolean exceptionCaught = false;
382     try {
383       handler.increment(table, increment);
384     } catch (TIOError e) {
385       exceptionCaught = true;
386       assertTrue(e.getCause() instanceof DoNotRetryIOException);
387       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
388     } finally {
389       assertTrue(exceptionCaught);
390     }
391   }
392 
393   @Test
394   public void testAppendWithReadOnly() throws Exception {
395     ThriftHBaseServiceHandler handler = createHandler();
396     byte[] rowName = "testAppend".getBytes();
397     ByteBuffer table = wrap(tableAname);
398     byte[] v1 = Bytes.toBytes("42");
399 
400     List<TColumnValue> appendColumns = new ArrayList<>(1);
401     appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(v1)));
402     TAppend append = new TAppend(wrap(rowName), appendColumns);
403 
404     boolean exceptionCaught = false;
405     try {
406       handler.append(table, append);
407     } catch (TIOError e) {
408       exceptionCaught = true;
409       assertTrue(e.getCause() instanceof DoNotRetryIOException);
410       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
411     } finally {
412       assertTrue(exceptionCaught);
413     }
414   }
415 
416   @Test
417   public void testMutateRowWithReadOnly() throws Exception {
418     ThriftHBaseServiceHandler handler = createHandler();
419     byte[] rowName = "testMutateRow".getBytes();
420     ByteBuffer table = wrap(tableAname);
421 
422     List<TColumnValue> columnValuesA = new ArrayList<>(1);
423     TColumnValue columnValueA = new TColumnValue(wrap(familyAname), wrap(qualifierAname),
424         wrap(valueAname));
425     columnValuesA.add(columnValueA);
426     TPut putA = new TPut(wrap(rowName), columnValuesA);
427     putA.setColumnValues(columnValuesA);
428 
429     TDelete delete = new TDelete(wrap(rowName));
430 
431     List<TMutation> mutations = new ArrayList<>(2);
432     TMutation mutationA = TMutation.put(putA);
433     mutations.add(mutationA);
434     TMutation mutationB = TMutation.deleteSingle(delete);
435     mutations.add(mutationB);
436     TRowMutations tRowMutations = new TRowMutations(wrap(rowName),mutations);
437 
438     boolean exceptionCaught = false;
439     try {
440       handler.mutateRow(table,tRowMutations);
441     } catch (TIOError e) {
442       exceptionCaught = true;
443       assertTrue(e.getCause() instanceof DoNotRetryIOException);
444       assertEquals("Thrift Server is in Read-only mode.", e.getMessage());
445     } finally {
446       assertTrue(exceptionCaught);
447     }
448   }
449 
450   @Test
451   public void testScanWithReadOnly() throws Exception {
452     ThriftHBaseServiceHandler handler = createHandler();
453     ByteBuffer table = wrap(tableAname);
454 
455     TScan scan = new TScan();
456     boolean exceptionCaught = false;
457     try {
458       int scanId = handler.openScanner(table, scan);
459       handler.getScannerRows(scanId, 10);
460       handler.closeScanner(scanId);
461     } catch (TIOError e) {
462       exceptionCaught = true;
463     } finally {
464       assertFalse(exceptionCaught);
465     }
466   }
467 }