001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.thrift2;
019
020import static org.apache.hadoop.hbase.thrift.Constants.THRIFT_INFO_SERVER_PORT;
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertFalse;
023import static org.junit.Assert.assertNotNull;
024import static org.junit.Assert.assertNull;
025import static org.junit.Assert.assertTrue;
026
027import java.io.IOException;
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.Iterator;
031import java.util.List;
032import org.apache.hadoop.conf.Configuration;
033import org.apache.hadoop.hbase.Cell;
034import org.apache.hadoop.hbase.CellUtil;
035import org.apache.hadoop.hbase.CompareOperator;
036import org.apache.hadoop.hbase.HBaseClassTestRule;
037import org.apache.hadoop.hbase.HBaseConfiguration;
038import org.apache.hadoop.hbase.HBaseTestingUtil;
039import org.apache.hadoop.hbase.HConstants;
040import org.apache.hadoop.hbase.NamespaceDescriptor;
041import org.apache.hadoop.hbase.TableName;
042import org.apache.hadoop.hbase.client.Admin;
043import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
044import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
045import org.apache.hadoop.hbase.client.Connection;
046import org.apache.hadoop.hbase.client.ConnectionFactory;
047import org.apache.hadoop.hbase.client.ConnectionUtils;
048import org.apache.hadoop.hbase.client.Delete;
049import org.apache.hadoop.hbase.client.Durability;
050import org.apache.hadoop.hbase.client.Get;
051import org.apache.hadoop.hbase.client.Put;
052import org.apache.hadoop.hbase.client.Result;
053import org.apache.hadoop.hbase.client.ResultScanner;
054import org.apache.hadoop.hbase.client.Scan;
055import org.apache.hadoop.hbase.client.Table;
056import org.apache.hadoop.hbase.client.TableDescriptor;
057import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
058import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
059import org.apache.hadoop.hbase.filter.ColumnValueFilter;
060import org.apache.hadoop.hbase.filter.FilterList;
061import org.apache.hadoop.hbase.filter.PrefixFilter;
062import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
063import org.apache.hadoop.hbase.testclassification.MediumTests;
064import org.apache.hadoop.hbase.testclassification.RestTests;
065import org.apache.hadoop.hbase.thrift.Constants;
066import org.apache.hadoop.hbase.thrift2.client.ThriftConnection;
067import org.apache.hadoop.hbase.util.Bytes;
068import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
069import org.junit.AfterClass;
070import org.junit.BeforeClass;
071import org.junit.ClassRule;
072import org.junit.Test;
073import org.junit.experimental.categories.Category;
074import org.slf4j.Logger;
075import org.slf4j.LoggerFactory;
076
077@Category({ RestTests.class, MediumTests.class })
078
079public class TestThriftConnection {
080  private static final Logger LOG = LoggerFactory.getLogger(TestThriftConnection.class);
081
082  @ClassRule
083  public static final HBaseClassTestRule CLASS_RULE =
084    HBaseClassTestRule.forClass(TestThriftConnection.class);
085
086  private static final byte[] FAMILYA = Bytes.toBytes("fa");
087  private static final byte[] FAMILYB = Bytes.toBytes("fb");
088  private static final byte[] FAMILYC = Bytes.toBytes("fc");
089  private static final byte[] FAMILYD = Bytes.toBytes("fd");
090
091  private static final byte[] ROW_1 = Bytes.toBytes("testrow1");
092  private static final byte[] ROW_2 = Bytes.toBytes("testrow2");
093  private static final byte[] ROW_3 = Bytes.toBytes("testrow3");
094  private static final byte[] ROW_4 = Bytes.toBytes("testrow4");
095
096  private static final byte[] QUALIFIER_1 = Bytes.toBytes("1");
097  private static final byte[] QUALIFIER_2 = Bytes.toBytes("2");
098  private static final byte[] VALUE_1 = Bytes.toBytes("testvalue1");
099  private static final byte[] VALUE_2 = Bytes.toBytes("testvalue2");
100
101  private static final long ONE_HOUR = 60 * 60 * 1000;
102  private static final long TS_2 = EnvironmentEdgeManager.currentTime();
103  private static final long TS_1 = TS_2 - ONE_HOUR;
104
105  protected static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
106
107  protected static ThriftServer thriftServer;
108
109  protected static ThriftServer thriftHttpServer;
110
111  protected static int thriftPort;
112  protected static int httpPort;
113
114  protected static Connection thriftConnection;
115  protected static Connection thriftHttpConnection;
116
117  private static Admin thriftAdmin;
118
119  private static ThriftServer startThriftServer(int port, boolean useHttp) {
120    Configuration thriftServerConf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
121    thriftServerConf.setInt(Constants.PORT_CONF_KEY, port);
122    if (useHttp) {
123      thriftServerConf.setBoolean(Constants.USE_HTTP_CONF_KEY, true);
124    }
125    ThriftServer server = new ThriftServer(thriftServerConf);
126    Thread thriftServerThread = new Thread(() -> {
127      try {
128        server.run();
129      } catch (Exception t) {
130        LOG.error("Thrift Server failed", t);
131      }
132    });
133    thriftServerThread.setDaemon(true);
134    thriftServerThread.start();
135    if (useHttp) {
136      TEST_UTIL.waitFor(10000, () -> server.getHttpServer() != null);
137    } else {
138      TEST_UTIL.waitFor(10000, () -> server.getTserver() != null);
139    }
140    return server;
141  }
142
143  private static Connection createConnection(int port, boolean useHttp) throws IOException {
144    Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
145    conf.set(ConnectionUtils.HBASE_CLIENT_CONNECTION_IMPL, ThriftConnection.class.getName());
146    if (useHttp) {
147      conf.set(Constants.HBASE_THRIFT_CLIENT_BUIDLER_CLASS,
148        ThriftConnection.HTTPThriftClientBuilder.class.getName());
149    }
150    String host = HConstants.LOCALHOST;
151    if (useHttp) {
152      host = "http://" + host;
153    }
154    conf.set(Constants.HBASE_THRIFT_SERVER_NAME, host);
155    conf.setInt(Constants.HBASE_THRIFT_SERVER_PORT, port);
156    return ConnectionFactory.createConnection(conf);
157  }
158
159  @BeforeClass
160  public static void setUp() throws Exception {
161    // Do not start info server
162    TEST_UTIL.getConfiguration().setInt(THRIFT_INFO_SERVER_PORT, -1);
163    TEST_UTIL.startMiniCluster();
164    thriftPort = HBaseTestingUtil.randomFreePort();
165    httpPort = HBaseTestingUtil.randomFreePort();
166    // Start a thrift server
167    thriftServer = startThriftServer(thriftPort, false);
168    // Start an HTTP thrift server
169    thriftHttpServer = startThriftServer(httpPort, true);
170    thriftConnection = createConnection(thriftPort, false);
171    thriftHttpConnection = createConnection(httpPort, true);
172    thriftAdmin = thriftConnection.getAdmin();
173    LOG.info("TS_1=" + TS_1);
174    LOG.info("TS_2=" + TS_1);
175
176  }
177
178  @AfterClass
179  public static void shutdown() throws Exception {
180    if (thriftAdmin != null) {
181      thriftAdmin.close();
182    }
183    if (thriftHttpConnection != null) {
184      thriftHttpConnection.close();
185    }
186    if (thriftConnection != null) {
187      thriftConnection.close();
188    }
189    if (thriftHttpServer != null) {
190      thriftHttpServer.stop();
191    }
192    TEST_UTIL.shutdownMiniCluster();
193  }
194
195  @Test
196  public void testGetClusterId() {
197    String actualClusterId = TEST_UTIL.getMiniHBaseCluster().getMaster().getClusterId();
198    for (Connection conn : new Connection[] { thriftConnection, thriftHttpConnection }) {
199      String thriftClusterId = conn.getClusterId();
200      assertEquals(actualClusterId, thriftClusterId);
201    }
202  }
203
204  @Test
205  public void testThriftAdmin() throws Exception {
206    testThriftAdmin(thriftConnection, "testThriftAdminNamespace", "testThriftAdminTable");
207    testThriftAdmin(thriftHttpConnection, "testThriftHttpAdminNamespace",
208      "testThriftHttpAdminTable");
209  }
210
211  @Test
212  public void testGet() throws Exception {
213    testGet(thriftConnection, "testGetTable");
214    testGet(thriftHttpConnection, "testGetHttpTable");
215
216  }
217
218  private void testGet(Connection connection, String tableName) throws IOException {
219    createTable(thriftAdmin, tableName);
220    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
221      Get get = new Get(ROW_1);
222      Result result = table.get(get);
223      byte[] value1 = result.getValue(FAMILYA, QUALIFIER_1);
224      byte[] value2 = result.getValue(FAMILYB, QUALIFIER_2);
225      assertNotNull(value1);
226      assertTrue(Bytes.equals(VALUE_1, value1));
227      assertNull(value2);
228
229      get = new Get(ROW_1);
230      get.addFamily(FAMILYC);
231      result = table.get(get);
232      value1 = result.getValue(FAMILYA, QUALIFIER_1);
233      value2 = result.getValue(FAMILYB, QUALIFIER_2);
234      assertNull(value1);
235      assertNull(value2);
236
237      get = new Get(ROW_1);
238      get.addColumn(FAMILYA, QUALIFIER_1);
239      get.addColumn(FAMILYB, QUALIFIER_2);
240      result = table.get(get);
241      value1 = result.getValue(FAMILYA, QUALIFIER_1);
242      value2 = result.getValue(FAMILYB, QUALIFIER_2);
243      assertNotNull(value1);
244      assertTrue(Bytes.equals(VALUE_1, value1));
245      assertNull(value2);
246
247      get = new Get(ROW_2);
248      result = table.get(get);
249      value1 = result.getValue(FAMILYA, QUALIFIER_1);
250      value2 = result.getValue(FAMILYB, QUALIFIER_2);
251      assertNotNull(value1);
252      assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
253      assertNotNull(value2);
254      assertTrue(Bytes.equals(VALUE_2, value2));
255
256      get = new Get(ROW_2);
257      get.addFamily(FAMILYA);
258      result = table.get(get);
259      value1 = result.getValue(FAMILYA, QUALIFIER_1);
260      value2 = result.getValue(FAMILYB, QUALIFIER_2);
261      assertNotNull(value1);
262      assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
263      assertNull(value2);
264
265      get = new Get(ROW_2);
266      get.addColumn(FAMILYA, QUALIFIER_1);
267      get.addColumn(FAMILYB, QUALIFIER_2);
268      result = table.get(get);
269      value1 = result.getValue(FAMILYA, QUALIFIER_1);
270      value2 = result.getValue(FAMILYB, QUALIFIER_2);
271      assertNotNull(value1);
272      assertTrue(Bytes.equals(VALUE_2, value1)); // @TS_2
273      assertNotNull(value2);
274      assertTrue(Bytes.equals(VALUE_2, value2));
275
276      // test timestamp
277
278      get = new Get(ROW_2);
279      get.addFamily(FAMILYA);
280      get.addFamily(FAMILYB);
281      get.setTimestamp(TS_1);
282      result = table.get(get);
283      value1 = result.getValue(FAMILYA, QUALIFIER_1);
284      value2 = result.getValue(FAMILYB, QUALIFIER_2);
285      assertNotNull(value1);
286      assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
287      assertNull(value2);
288
289      // test timerange
290
291      get = new Get(ROW_2);
292      get.addFamily(FAMILYA);
293      get.addFamily(FAMILYB);
294      get.setTimeRange(0, TS_1 + 1);
295      result = table.get(get);
296      value1 = result.getValue(FAMILYA, QUALIFIER_1);
297      value2 = result.getValue(FAMILYB, QUALIFIER_2);
298      assertNotNull(value1);
299      assertTrue(Bytes.equals(VALUE_1, value1)); // @TS_1
300      assertNull(value2);
301
302      // test maxVersions
303
304      get = new Get(ROW_2);
305      get.addFamily(FAMILYA);
306      get.readVersions(2);
307      result = table.get(get);
308      int count = 0;
309      for (Cell kv : result.listCells()) {
310        if (CellUtil.matchingFamily(kv, FAMILYA) && TS_1 == kv.getTimestamp()) {
311          assertTrue(CellUtil.matchingValue(kv, VALUE_1)); // @TS_1
312          count++;
313        }
314        if (CellUtil.matchingFamily(kv, FAMILYA) && TS_2 == kv.getTimestamp()) {
315          assertTrue(CellUtil.matchingValue(kv, VALUE_2)); // @TS_2
316          count++;
317        }
318      }
319      assertEquals(2, count);
320    }
321
322  }
323
324  @Test
325  public void testHBASE22011() throws Exception {
326    testHBASE22011(thriftConnection, "testHBASE22011Table");
327    testHBASE22011(thriftHttpConnection, "testHBASE22011HttpTable");
328  }
329
330  public void testHBASE22011(Connection connection, String tableName) throws IOException {
331    createTable(thriftAdmin, tableName);
332    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
333      Get get = new Get(ROW_2);
334      Result result = table.get(get);
335      assertEquals(2, result.listCells().size());
336
337      ColumnCountGetFilter filter = new ColumnCountGetFilter(1);
338      get.setFilter(filter);
339      result = table.get(get);
340      assertEquals(1, result.listCells().size());
341    }
342  }
343
344  @Test
345  public void testMultiGet() throws Exception {
346    testMultiGet(thriftConnection, "testMultiGetTable");
347    testMultiGet(thriftHttpConnection, "testMultiGetHttpTable");
348  }
349
350  public void testMultiGet(Connection connection, String tableName) throws Exception {
351    createTable(thriftAdmin, tableName);
352    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
353      ArrayList<Get> gets = new ArrayList<>(2);
354      gets.add(new Get(ROW_1));
355      gets.add(new Get(ROW_2));
356      Result[] results = table.get(gets);
357      assertNotNull(results);
358      assertEquals(2, results.length);
359      assertEquals(1, results[0].size());
360      assertEquals(2, results[1].size());
361
362      // Test Versions
363      gets = new ArrayList<>(2);
364      Get g = new Get(ROW_1);
365      g.readVersions(3);
366      gets.add(g);
367      Get get2 = new Get(ROW_2);
368      get2.readVersions(3);
369      gets.add(get2);
370      results = table.get(gets);
371      assertNotNull(results);
372      assertEquals(2, results.length);
373      assertEquals(1, results[0].size());
374      assertEquals(3, results[1].size());
375
376      gets = new ArrayList<>(1);
377      gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
378      results = table.get(gets);
379      assertNotNull(results);
380      assertTrue(results[0].isEmpty());
381
382      gets = new ArrayList<>(3);
383      gets.add(new Get(Bytes.toBytes("RESALLYREALLYNOTTHERE")));
384      gets.add(new Get(ROW_1));
385      gets.add(new Get(ROW_2));
386      results = table.get(gets);
387      assertNotNull(results);
388      assertEquals(3, results.length);
389      assertTrue(results[0].isEmpty());
390    }
391
392  }
393
394  @Test
395  public void testPut() throws Exception {
396    testPut(thriftConnection, "testPutTable");
397    testPut(thriftHttpConnection, "testPutHttpTable");
398  }
399
400  public void testPut(Connection connection, String tableName) throws IOException {
401    createTable(thriftAdmin, tableName);
402    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
403      Put put = new Put(ROW_3);
404      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
405      table.put(put);
406
407      Get get = new Get(ROW_3);
408      get.addFamily(FAMILYA);
409      Result result = table.get(get);
410      byte[] value = result.getValue(FAMILYA, QUALIFIER_1);
411      assertNotNull(value);
412      assertTrue(Bytes.equals(VALUE_1, value));
413
414      // multiput
415
416      List<Put> puts = new ArrayList<>(3);
417      put = new Put(ROW_3);
418      put.addColumn(FAMILYB, QUALIFIER_2, VALUE_2);
419      puts.add(put);
420      put = new Put(ROW_4);
421      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
422      puts.add(put);
423      put = new Put(ROW_4);
424      put.addColumn(FAMILYB, QUALIFIER_2, VALUE_2);
425      puts.add(put);
426      table.put(puts);
427
428      get = new Get(ROW_3);
429      get.addFamily(FAMILYB);
430      result = table.get(get);
431      value = result.getValue(FAMILYB, QUALIFIER_2);
432      assertNotNull(value);
433      assertTrue(Bytes.equals(VALUE_2, value));
434      get = new Get(ROW_4);
435      result = table.get(get);
436      value = result.getValue(FAMILYA, QUALIFIER_1);
437      assertNotNull(value);
438      assertTrue(Bytes.equals(VALUE_1, value));
439      value = result.getValue(FAMILYB, QUALIFIER_2);
440      assertNotNull(value);
441      assertTrue(Bytes.equals(VALUE_2, value));
442    }
443  }
444
445  @Test
446  public void testDelete() throws Exception {
447    testDelete(thriftConnection, "testDeleteTable");
448    testDelete(thriftHttpConnection, "testDeleteHttpTable");
449  }
450
451  public void testDelete(Connection connection, String tableName) throws IOException {
452    createTable(thriftAdmin, tableName);
453    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
454      Put put = new Put(ROW_3);
455      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
456      put.addColumn(FAMILYB, QUALIFIER_2, VALUE_2);
457      put.addColumn(FAMILYC, QUALIFIER_1, VALUE_1);
458      put.addColumn(FAMILYC, QUALIFIER_2, VALUE_2);
459      table.put(put);
460
461      Get get = new Get(ROW_3);
462      get.addFamily(FAMILYA);
463      get.addFamily(FAMILYB);
464      get.addFamily(FAMILYC);
465      Result result = table.get(get);
466      byte[] value1 = result.getValue(FAMILYA, QUALIFIER_1);
467      byte[] value2 = result.getValue(FAMILYB, QUALIFIER_2);
468      byte[] value3 = result.getValue(FAMILYC, QUALIFIER_1);
469      byte[] value4 = result.getValue(FAMILYC, QUALIFIER_2);
470      assertNotNull(value1);
471      assertTrue(Bytes.equals(VALUE_1, value1));
472      assertNotNull(value2);
473      assertTrue(Bytes.equals(VALUE_2, value2));
474      assertNotNull(value3);
475      assertTrue(Bytes.equals(VALUE_1, value3));
476      assertNotNull(value4);
477      assertTrue(Bytes.equals(VALUE_2, value4));
478
479      Delete delete = new Delete(ROW_3);
480      delete.addColumn(FAMILYB, QUALIFIER_2);
481      table.delete(delete);
482
483      get = new Get(ROW_3);
484      get.addFamily(FAMILYA);
485      get.addFamily(FAMILYB);
486      result = table.get(get);
487      value1 = result.getValue(FAMILYA, QUALIFIER_1);
488      value2 = result.getValue(FAMILYB, QUALIFIER_2);
489      assertNotNull(value1);
490      assertTrue(Bytes.equals(VALUE_1, value1));
491      assertNull(value2);
492
493      delete = new Delete(ROW_3);
494      delete.setTimestamp(1L);
495      table.delete(delete);
496
497      get = new Get(ROW_3);
498      get.addFamily(FAMILYA);
499      get.addFamily(FAMILYB);
500      result = table.get(get);
501      value1 = result.getValue(FAMILYA, QUALIFIER_1);
502      value2 = result.getValue(FAMILYB, QUALIFIER_2);
503      assertNotNull(value1);
504      assertTrue(Bytes.equals(VALUE_1, value1));
505      assertNull(value2);
506
507      // Delete column family from row
508      delete = new Delete(ROW_3);
509      delete.addFamily(FAMILYC);
510      table.delete(delete);
511
512      get = new Get(ROW_3);
513      get.addFamily(FAMILYC);
514      result = table.get(get);
515      value3 = result.getValue(FAMILYC, QUALIFIER_1);
516      value4 = result.getValue(FAMILYC, QUALIFIER_2);
517      assertNull(value3);
518      assertNull(value4);
519
520      delete = new Delete(ROW_3);
521      table.delete(delete);
522
523      get = new Get(ROW_3);
524      get.addFamily(FAMILYA);
525      get.addFamily(FAMILYB);
526      result = table.get(get);
527      value1 = result.getValue(FAMILYA, QUALIFIER_1);
528      value2 = result.getValue(FAMILYB, QUALIFIER_2);
529      assertNull(value1);
530      assertNull(value2);
531    }
532
533  }
534
535  @Test
536  public void testScanner() throws Exception {
537    testScanner(thriftConnection, "testScannerTable");
538    testScanner(thriftHttpConnection, "testScannerHttpTable");
539  }
540
541  public void testScanner(Connection connection, String tableName) throws IOException {
542    createTable(thriftAdmin, tableName);
543    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
544      List<Put> puts = new ArrayList<>(4);
545      Put put = new Put(ROW_1);
546      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
547      puts.add(put);
548      put = new Put(ROW_2);
549      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
550      puts.add(put);
551      put = new Put(ROW_3);
552      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
553      puts.add(put);
554      put = new Put(ROW_4);
555      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
556      puts.add(put);
557      table.put(puts);
558
559      ResultScanner scanner = table.getScanner(new Scan());
560
561      Result[] results = scanner.next(1);
562      assertNotNull(results);
563      assertEquals(1, results.length);
564      assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
565
566      Result result = scanner.next();
567      assertNotNull(result);
568      assertTrue(Bytes.equals(ROW_2, result.getRow()));
569
570      results = scanner.next(2);
571      assertNotNull(results);
572      assertEquals(2, results.length);
573      assertTrue(Bytes.equals(ROW_3, results[0].getRow()));
574      assertTrue(Bytes.equals(ROW_4, results[1].getRow()));
575
576      results = scanner.next(1);
577      assertTrue(results == null || results.length == 0);
578      scanner.close();
579
580      scanner = table.getScanner(FAMILYA);
581      results = scanner.next(4);
582      assertNotNull(results);
583      assertEquals(4, results.length);
584      assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
585      assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
586      assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
587      assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
588
589      scanner.close();
590
591      scanner = table.getScanner(FAMILYA, QUALIFIER_1);
592      results = scanner.next(4);
593      assertNotNull(results);
594      assertEquals(4, results.length);
595      assertTrue(Bytes.equals(ROW_1, results[0].getRow()));
596      assertTrue(Bytes.equals(ROW_2, results[1].getRow()));
597      assertTrue(Bytes.equals(ROW_3, results[2].getRow()));
598      assertTrue(Bytes.equals(ROW_4, results[3].getRow()));
599      scanner.close();
600    }
601
602  }
603
604  @Test
605  public void testCheckAndDelete() throws Exception {
606    testCheckAndDelete(thriftConnection, "testCheckAndDeleteTable");
607    testCheckAndDelete(thriftHttpConnection, "testCheckAndDeleteHttpTable");
608  }
609
610  public void testCheckAndDelete(Connection connection, String tableName) throws IOException {
611    createTable(thriftAdmin, tableName);
612    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
613      Get get = new Get(ROW_1);
614      Result result = table.get(get);
615      byte[] value1 = result.getValue(FAMILYA, QUALIFIER_1);
616      byte[] value2 = result.getValue(FAMILYB, QUALIFIER_2);
617      assertNotNull(value1);
618      assertTrue(Bytes.equals(VALUE_1, value1));
619      assertNull(value2);
620      assertTrue(table.exists(get));
621      assertEquals(1, table.exists(Collections.singletonList(get)).length);
622      Delete delete = new Delete(ROW_1);
623
624      table.checkAndMutate(ROW_1, FAMILYA).qualifier(QUALIFIER_1).ifEquals(VALUE_1)
625        .thenDelete(delete);
626      assertFalse(table.exists(get));
627
628      Put put = new Put(ROW_1);
629      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
630      table.put(put);
631
632      assertTrue(
633        table.checkAndMutate(ROW_1, FAMILYA).qualifier(QUALIFIER_1).ifEquals(VALUE_1).thenPut(put));
634      assertFalse(
635        table.checkAndMutate(ROW_1, FAMILYA).qualifier(QUALIFIER_1).ifEquals(VALUE_2).thenPut(put));
636    }
637
638  }
639
640  @Test
641  public void testIteratorScaner() throws Exception {
642    testIteratorScanner(thriftConnection, "testIteratorScanerTable");
643    testIteratorScanner(thriftHttpConnection, "testIteratorScanerHttpTable");
644  }
645
646  public void testIteratorScanner(Connection connection, String tableName) throws IOException {
647    createTable(thriftAdmin, tableName);
648    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
649      List<Put> puts = new ArrayList<>(4);
650      Put put = new Put(ROW_1);
651      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
652      puts.add(put);
653      put = new Put(ROW_2);
654      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
655      puts.add(put);
656      put = new Put(ROW_3);
657      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
658      puts.add(put);
659      put = new Put(ROW_4);
660      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
661      puts.add(put);
662      table.put(puts);
663      Scan scan = new Scan();
664      scan.setCaching(1);
665      ResultScanner scanner = table.getScanner(scan);
666      Iterator<Result> iterator = scanner.iterator();
667      assertTrue(iterator.hasNext());
668      int counter = 0;
669      while (iterator.hasNext()) {
670        iterator.next();
671        counter++;
672      }
673      assertEquals(4, counter);
674    }
675
676  }
677
678  @Test
679  public void testReverseScan() throws Exception {
680    testReverseScan(thriftConnection, "testReverseScanTable");
681    testReverseScan(thriftHttpConnection, "testReverseScanHttpTable");
682  }
683
684  public void testReverseScan(Connection connection, String tableName) throws IOException {
685    createTable(thriftAdmin, tableName);
686    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
687      List<Put> puts = new ArrayList<>(4);
688      Put put = new Put(ROW_1);
689      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
690      puts.add(put);
691      put = new Put(ROW_2);
692      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
693      puts.add(put);
694      put = new Put(ROW_3);
695      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
696      puts.add(put);
697      put = new Put(ROW_4);
698      put.addColumn(FAMILYA, QUALIFIER_1, VALUE_1);
699      puts.add(put);
700      table.put(puts);
701      Scan scan = new Scan();
702      scan.setReversed(true);
703      scan.setCaching(1);
704      ResultScanner scanner = table.getScanner(scan);
705      Iterator<Result> iterator = scanner.iterator();
706      assertTrue(iterator.hasNext());
707      int counter = 0;
708      Result lastResult = null;
709      while (iterator.hasNext()) {
710        Result current = iterator.next();
711        if (lastResult != null) {
712          assertTrue(Bytes.compareTo(lastResult.getRow(), current.getRow()) > 0);
713        }
714        lastResult = current;
715        counter++;
716      }
717      assertEquals(4, counter);
718    }
719
720  }
721
722  @Test
723  public void testScanWithFilters() throws Exception {
724    testScanWithFilters(thriftConnection, "testScanWithFiltersTable");
725    testScanWithFilters(thriftHttpConnection, "testScanWithFiltersHttpTable");
726  }
727
728  private void testScanWithFilters(Connection connection, String tableName) throws IOException {
729    createTable(thriftAdmin, tableName);
730    try (Table table = connection.getTable(TableName.valueOf(tableName))) {
731      FilterList filterList = new FilterList();
732      PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("testrow"));
733      ColumnValueFilter columnValueFilter =
734        new ColumnValueFilter(FAMILYA, QUALIFIER_1, CompareOperator.EQUAL, VALUE_1);
735      filterList.addFilter(prefixFilter);
736      filterList.addFilter(columnValueFilter);
737      Scan scan = new Scan();
738      scan.readVersions(2);
739      scan.setFilter(filterList);
740      ResultScanner scanner = table.getScanner(scan);
741      Iterator<Result> iterator = scanner.iterator();
742      assertTrue(iterator.hasNext());
743      int counter = 0;
744      while (iterator.hasNext()) {
745        Result result = iterator.next();
746        counter += result.size();
747      }
748      assertEquals(2, counter);
749    }
750  }
751
752  private TableDescriptor createTable(Admin admin, String tableName) throws IOException {
753    TableDescriptorBuilder builder =
754      TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName));
755    ColumnFamilyDescriptorBuilder familyABuilder =
756      ColumnFamilyDescriptorBuilder.newBuilder(FAMILYA);
757    familyABuilder.setMaxVersions(3);
758    ColumnFamilyDescriptorBuilder familyBBuilder =
759      ColumnFamilyDescriptorBuilder.newBuilder(FAMILYB);
760    familyBBuilder.setMaxVersions(3);
761    ColumnFamilyDescriptorBuilder familyCBuilder =
762      ColumnFamilyDescriptorBuilder.newBuilder(FAMILYC);
763    familyCBuilder.setMaxVersions(3);
764    builder.setColumnFamily(familyABuilder.build());
765    builder.setColumnFamily(familyBBuilder.build());
766    builder.setColumnFamily(familyCBuilder.build());
767    TableDescriptor tableDescriptor = builder.build();
768    admin.createTable(tableDescriptor);
769    try (Table table = TEST_UTIL.getConnection().getTable(TableName.valueOf(tableName))) {
770      Put put = new Put(ROW_1);
771      put.addColumn(FAMILYA, QUALIFIER_1, TS_2, VALUE_1);
772      table.put(put);
773      put = new Put(ROW_2);
774      put.addColumn(FAMILYA, QUALIFIER_1, TS_1, VALUE_1);
775      put.addColumn(FAMILYA, QUALIFIER_1, TS_2, VALUE_2);
776      put.addColumn(FAMILYB, QUALIFIER_2, TS_2, VALUE_2);
777      table.put(put);
778
779    }
780    return tableDescriptor;
781
782  }
783
784  private void testThriftAdmin(Connection connection, String namespace, String table)
785    throws Exception {
786    try (Admin admin = connection.getAdmin()) {
787      // create name space
788      NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(namespace).build();
789      namespaceDescriptor.setConfiguration("key1", "value1");
790      namespaceDescriptor.setConfiguration("key2", "value2");
791      admin.createNamespace(namespaceDescriptor);
792      // list namespace
793      NamespaceDescriptor[] namespaceDescriptors = admin.listNamespaceDescriptors();
794      boolean found = false;
795      for (NamespaceDescriptor nd : namespaceDescriptors) {
796        if (nd.getName().equals(namespace)) {
797          found = true;
798          break;
799        }
800      }
801      assertTrue(found);
802      // modify namesapce
803      namespaceDescriptor.setConfiguration("kye3", "value3");
804      admin.modifyNamespace(namespaceDescriptor);
805      // get namespace
806      NamespaceDescriptor namespaceDescriptorReturned = admin.getNamespaceDescriptor(namespace);
807      assertTrue(namespaceDescriptorReturned.getConfiguration().size() == 3);
808      // create table
809      TableDescriptor tableDescriptor = createTable(admin, table);
810      // modify table
811      TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableDescriptor);
812      builder.setDurability(Durability.ASYNC_WAL);
813      admin.modifyTable(builder.build());
814      // modify column family
815      ColumnFamilyDescriptor familyA = tableDescriptor.getColumnFamily(FAMILYA);
816      ColumnFamilyDescriptorBuilder familyABuilder =
817        ColumnFamilyDescriptorBuilder.newBuilder(familyA);
818      familyABuilder.setInMemory(true);
819      admin.modifyColumnFamily(tableDescriptor.getTableName(), familyABuilder.build());
820      // add column family
821      ColumnFamilyDescriptorBuilder familyDBuilder =
822        ColumnFamilyDescriptorBuilder.newBuilder(FAMILYD);
823      familyDBuilder.setDataBlockEncoding(DataBlockEncoding.PREFIX);
824      admin.addColumnFamily(tableDescriptor.getTableName(), familyDBuilder.build());
825      // get table descriptor
826      TableDescriptor tableDescriptorReturned = admin.getDescriptor(tableDescriptor.getTableName());
827      assertTrue(tableDescriptorReturned.getColumnFamilies().length == 4);
828      assertTrue(tableDescriptorReturned.getDurability() == Durability.ASYNC_WAL);
829      ColumnFamilyDescriptor columnFamilyADescriptor1Returned =
830        tableDescriptorReturned.getColumnFamily(FAMILYA);
831      assertTrue(columnFamilyADescriptor1Returned.isInMemory() == true);
832      // delete column family
833      admin.deleteColumnFamily(tableDescriptor.getTableName(), FAMILYA);
834      tableDescriptorReturned = admin.getDescriptor(tableDescriptor.getTableName());
835      assertTrue(tableDescriptorReturned.getColumnFamilies().length == 3);
836      // disable table
837      admin.disableTable(tableDescriptor.getTableName());
838      assertTrue(admin.isTableDisabled(tableDescriptor.getTableName()));
839      // enable table
840      admin.enableTable(tableDescriptor.getTableName());
841      assertTrue(admin.isTableEnabled(tableDescriptor.getTableName()));
842      assertTrue(admin.isTableAvailable(tableDescriptor.getTableName()));
843      // truncate table
844      admin.disableTable(tableDescriptor.getTableName());
845      admin.truncateTable(tableDescriptor.getTableName(), true);
846      assertTrue(admin.isTableAvailable(tableDescriptor.getTableName()));
847      // delete table
848      admin.disableTable(tableDescriptor.getTableName());
849      admin.deleteTable(tableDescriptor.getTableName());
850      assertFalse(admin.tableExists(tableDescriptor.getTableName()));
851      // delete namespace
852      admin.deleteNamespace(namespace);
853      namespaceDescriptors = admin.listNamespaceDescriptors();
854      // should have 2 namespace, default and hbase
855      found = false;
856      for (NamespaceDescriptor nd : namespaceDescriptors) {
857        if (nd.getName().equals(namespace)) {
858          found = true;
859          break;
860        }
861      }
862      assertTrue(found == false);
863    }
864  }
865}