001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.thrift2;
020
021import static org.apache.hadoop.hbase.thrift.Constants.THRIFT_READONLY_ENABLED;
022import static org.apache.hadoop.hbase.thrift.Constants.THRIFT_READONLY_ENABLED_DEFAULT;
023import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.appendFromThrift;
024import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.columnFamilyDescriptorFromThrift;
025import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.compareOpFromThrift;
026import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.deleteFromThrift;
027import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.deletesFromThrift;
028import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.getFromThrift;
029import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.getsFromThrift;
030import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.incrementFromThrift;
031import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.namespaceDescriptorFromHBase;
032import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.namespaceDescriptorFromThrift;
033import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.namespaceDescriptorsFromHBase;
034import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.putFromThrift;
035import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.putsFromThrift;
036import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.resultFromHBase;
037import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.resultsFromHBase;
038import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.rowMutationsFromThrift;
039import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.scanFromThrift;
040import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.splitKeyFromThrift;
041import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.tableDescriptorFromHBase;
042import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.tableDescriptorFromThrift;
043import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.tableDescriptorsFromHBase;
044import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.tableNameFromThrift;
045import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.tableNamesFromHBase;
046import static org.apache.thrift.TBaseHelper.byteBufferToByteArray;
047
048import java.io.IOException;
049import java.nio.ByteBuffer;
050import java.util.ArrayList;
051import java.util.Collections;
052import java.util.List;
053import java.util.Map;
054import java.util.Set;
055import java.util.concurrent.ConcurrentHashMap;
056import java.util.concurrent.atomic.AtomicInteger;
057import java.util.regex.Pattern;
058
059import org.apache.hadoop.conf.Configuration;
060import org.apache.hadoop.hbase.DoNotRetryIOException;
061import org.apache.hadoop.hbase.HRegionLocation;
062import org.apache.hadoop.hbase.NamespaceDescriptor;
063import org.apache.hadoop.hbase.ServerName;
064import org.apache.hadoop.hbase.TableName;
065import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
066import org.apache.hadoop.hbase.client.RegionLocator;
067import org.apache.hadoop.hbase.client.ResultScanner;
068import org.apache.hadoop.hbase.client.LogQueryFilter;
069import org.apache.hadoop.hbase.client.OnlineLogRecord;
070import org.apache.hadoop.hbase.client.Table;
071import org.apache.hadoop.hbase.client.TableDescriptor;
072import org.apache.hadoop.hbase.security.UserProvider;
073import org.apache.hadoop.hbase.thrift.HBaseServiceHandler;
074import org.apache.hadoop.hbase.thrift2.generated.TAppend;
075import org.apache.hadoop.hbase.thrift2.generated.TColumnFamilyDescriptor;
076import org.apache.hadoop.hbase.thrift2.generated.TCompareOp;
077import org.apache.hadoop.hbase.thrift2.generated.TDelete;
078import org.apache.hadoop.hbase.thrift2.generated.TGet;
079import org.apache.hadoop.hbase.thrift2.generated.THBaseService;
080import org.apache.hadoop.hbase.thrift2.generated.THRegionLocation;
081import org.apache.hadoop.hbase.thrift2.generated.TIOError;
082import org.apache.hadoop.hbase.thrift2.generated.TIllegalArgument;
083import org.apache.hadoop.hbase.thrift2.generated.TIncrement;
084import org.apache.hadoop.hbase.thrift2.generated.TLogQueryFilter;
085import org.apache.hadoop.hbase.thrift2.generated.TNamespaceDescriptor;
086import org.apache.hadoop.hbase.thrift2.generated.TOnlineLogRecord;
087import org.apache.hadoop.hbase.thrift2.generated.TPut;
088import org.apache.hadoop.hbase.thrift2.generated.TResult;
089import org.apache.hadoop.hbase.thrift2.generated.TRowMutations;
090import org.apache.hadoop.hbase.thrift2.generated.TScan;
091import org.apache.hadoop.hbase.thrift2.generated.TServerName;
092import org.apache.hadoop.hbase.thrift2.generated.TTableDescriptor;
093import org.apache.hadoop.hbase.thrift2.generated.TTableName;
094import org.apache.hadoop.hbase.thrift2.generated.TThriftServerType;
095import org.apache.hadoop.hbase.util.Bytes;
096import org.apache.thrift.TException;
097import org.apache.yetus.audience.InterfaceAudience;
098import org.slf4j.Logger;
099import org.slf4j.LoggerFactory;
100
101/**
102 * This class is a glue object that connects Thrift RPC calls to the HBase client API primarily
103 * defined in the Table interface.
104 */
105@InterfaceAudience.Private
106@SuppressWarnings("deprecation")
107public class ThriftHBaseServiceHandler extends HBaseServiceHandler implements THBaseService.Iface {
108
109  // TODO: Size of pool configuraple
110  private static final Logger LOG = LoggerFactory.getLogger(ThriftHBaseServiceHandler.class);
111
112  // nextScannerId and scannerMap are used to manage scanner state
113  // TODO: Cleanup thread for Scanners, Scanner id wrap
114  private final AtomicInteger nextScannerId = new AtomicInteger(0);
115  private final Map<Integer, ResultScanner> scannerMap = new ConcurrentHashMap<>();
116
117  private static final IOException ioe
118      = new DoNotRetryIOException("Thrift Server is in Read-only mode.");
119  private boolean isReadOnly;
120
121  private static class TIOErrorWithCause extends TIOError {
122    private Throwable cause;
123
124    public TIOErrorWithCause(Throwable cause) {
125      super();
126      this.cause = cause;
127    }
128
129    @Override
130    public synchronized Throwable getCause() {
131      return cause;
132    }
133
134    @Override
135    public boolean equals(Object other) {
136      if (super.equals(other) &&
137          other instanceof TIOErrorWithCause) {
138        Throwable otherCause = ((TIOErrorWithCause) other).getCause();
139        if (this.getCause() != null) {
140          return otherCause != null && this.getCause().equals(otherCause);
141        } else {
142          return otherCause == null;
143        }
144      }
145      return false;
146    }
147
148    @Override
149    public int hashCode() {
150      int result = super.hashCode();
151      result = 31 * result + (cause != null ? cause.hashCode() : 0);
152      return result;
153    }
154  }
155
156  public ThriftHBaseServiceHandler(final Configuration conf,
157      final UserProvider userProvider) throws IOException {
158    super(conf, userProvider);
159    isReadOnly = conf.getBoolean(THRIFT_READONLY_ENABLED, THRIFT_READONLY_ENABLED_DEFAULT);
160  }
161
162  @Override
163  protected Table getTable(ByteBuffer tableName) {
164    try {
165      return connectionCache.getTable(Bytes.toString(byteBufferToByteArray(tableName)));
166    } catch (IOException ie) {
167      throw new RuntimeException(ie);
168    }
169  }
170
171  private RegionLocator getLocator(ByteBuffer tableName) {
172    try {
173      return connectionCache.getRegionLocator(byteBufferToByteArray(tableName));
174    } catch (IOException ie) {
175      throw new RuntimeException(ie);
176    }
177  }
178
179  private void closeTable(Table table) throws TIOError {
180    try {
181      table.close();
182    } catch (IOException e) {
183      throw getTIOError(e);
184    }
185  }
186
187  private TIOError getTIOError(IOException e) {
188    TIOError err = new TIOErrorWithCause(e);
189    err.setMessage(e.getMessage());
190    return err;
191  }
192
193  /**
194   * Assigns a unique ID to the scanner and adds the mapping to an internal HashMap.
195   * @param scanner to add
196   * @return Id for this Scanner
197   */
198  private int addScanner(ResultScanner scanner) {
199    int id = nextScannerId.getAndIncrement();
200    scannerMap.put(id, scanner);
201    return id;
202  }
203
204  /**
205   * Returns the Scanner associated with the specified Id.
206   * @param id of the Scanner to get
207   * @return a Scanner, or null if the Id is invalid
208   */
209  private ResultScanner getScanner(int id) {
210    return scannerMap.get(id);
211  }
212
213  /**
214   * Removes the scanner associated with the specified ID from the internal HashMap.
215   * @param id of the Scanner to remove
216   * @return the removed Scanner, or <code>null</code> if the Id is invalid
217   */
218  protected ResultScanner removeScanner(int id) {
219    return scannerMap.remove(id);
220  }
221
222  @Override
223  public boolean exists(ByteBuffer table, TGet get) throws TIOError, TException {
224    Table htable = getTable(table);
225    try {
226      return htable.exists(getFromThrift(get));
227    } catch (IOException e) {
228      throw getTIOError(e);
229    } finally {
230      closeTable(htable);
231    }
232  }
233
234  @Override
235  public List<Boolean> existsAll(ByteBuffer table, List<TGet> gets) throws TIOError, TException {
236    Table htable = getTable(table);
237    try {
238      boolean[] exists = htable.existsAll(getsFromThrift(gets));
239      List<Boolean> result = new ArrayList<>(exists.length);
240      for (boolean exist : exists) {
241        result.add(exist);
242      }
243      return result;
244    } catch (IOException e) {
245      throw getTIOError(e);
246    } finally {
247      closeTable(htable);
248    }
249  }
250
251  @Override
252  public TResult get(ByteBuffer table, TGet get) throws TIOError, TException {
253    Table htable = getTable(table);
254    try {
255      return resultFromHBase(htable.get(getFromThrift(get)));
256    } catch (IOException e) {
257      throw getTIOError(e);
258    } finally {
259      closeTable(htable);
260    }
261  }
262
263  @Override
264  public List<TResult> getMultiple(ByteBuffer table, List<TGet> gets) throws TIOError, TException {
265    Table htable = getTable(table);
266    try {
267      return resultsFromHBase(htable.get(getsFromThrift(gets)));
268    } catch (IOException e) {
269      throw getTIOError(e);
270    } finally {
271      closeTable(htable);
272    }
273  }
274
275  @Override
276  public void put(ByteBuffer table, TPut put) throws TIOError, TException {
277    checkReadOnlyMode();
278    Table htable = getTable(table);
279    try {
280      htable.put(putFromThrift(put));
281    } catch (IOException e) {
282      throw getTIOError(e);
283    } finally {
284      closeTable(htable);
285    }
286  }
287
288  @Override
289  public boolean checkAndPut(ByteBuffer table, ByteBuffer row, ByteBuffer family,
290      ByteBuffer qualifier, ByteBuffer value, TPut put) throws TIOError, TException {
291    checkReadOnlyMode();
292    Table htable = getTable(table);
293    try {
294      Table.CheckAndMutateBuilder builder = htable.checkAndMutate(byteBufferToByteArray(row),
295          byteBufferToByteArray(family)).qualifier(byteBufferToByteArray(qualifier));
296      if (value == null) {
297        return builder.ifNotExists().thenPut(putFromThrift(put));
298      } else {
299        return builder.ifEquals(byteBufferToByteArray(value)).thenPut(putFromThrift(put));
300      }
301    } catch (IOException e) {
302      throw getTIOError(e);
303    } finally {
304      closeTable(htable);
305    }
306  }
307
308  @Override
309  public void putMultiple(ByteBuffer table, List<TPut> puts) throws TIOError, TException {
310    checkReadOnlyMode();
311    Table htable = getTable(table);
312    try {
313      htable.put(putsFromThrift(puts));
314    } catch (IOException e) {
315      throw getTIOError(e);
316    } finally {
317      closeTable(htable);
318    }
319  }
320
321  @Override
322  public void deleteSingle(ByteBuffer table, TDelete deleteSingle) throws TIOError, TException {
323    checkReadOnlyMode();
324    Table htable = getTable(table);
325    try {
326      htable.delete(deleteFromThrift(deleteSingle));
327    } catch (IOException e) {
328      throw getTIOError(e);
329    } finally {
330      closeTable(htable);
331    }
332  }
333
334  @Override
335  public List<TDelete> deleteMultiple(ByteBuffer table, List<TDelete> deletes) throws TIOError,
336      TException {
337    checkReadOnlyMode();
338    Table htable = getTable(table);
339    try {
340      htable.delete(deletesFromThrift(deletes));
341    } catch (IOException e) {
342      throw getTIOError(e);
343    } finally {
344      closeTable(htable);
345    }
346    return Collections.emptyList();
347  }
348  
349  @Override
350  public boolean checkAndMutate(ByteBuffer table, ByteBuffer row, ByteBuffer family,
351      ByteBuffer qualifier, TCompareOp compareOp, ByteBuffer value, TRowMutations rowMutations)
352          throws TIOError, TException {
353    checkReadOnlyMode();
354    try (final Table htable = getTable(table)) {
355      return htable.checkAndMutate(byteBufferToByteArray(row), byteBufferToByteArray(family))
356          .qualifier(byteBufferToByteArray(qualifier))
357          .ifMatches(compareOpFromThrift(compareOp), byteBufferToByteArray(value))
358          .thenMutate(rowMutationsFromThrift(rowMutations));
359    } catch (IOException e) {
360      throw getTIOError(e);
361    }
362  }
363
364  @Override
365  public boolean checkAndDelete(ByteBuffer table, ByteBuffer row, ByteBuffer family,
366      ByteBuffer qualifier, ByteBuffer value, TDelete deleteSingle) throws TIOError, TException {
367    checkReadOnlyMode();
368    Table htable = getTable(table);
369    try {
370      Table.CheckAndMutateBuilder mutateBuilder =
371          htable.checkAndMutate(byteBufferToByteArray(row), byteBufferToByteArray(family))
372              .qualifier(byteBufferToByteArray(qualifier));
373      if (value == null) {
374        return mutateBuilder.ifNotExists().thenDelete(deleteFromThrift(deleteSingle));
375      } else {
376        return mutateBuilder.ifEquals(byteBufferToByteArray(value))
377            .thenDelete(deleteFromThrift(deleteSingle));
378      }
379    } catch (IOException e) {
380      throw getTIOError(e);
381    } finally {
382      closeTable(htable);
383    }
384  }
385
386  @Override
387  public TResult increment(ByteBuffer table, TIncrement increment) throws TIOError, TException {
388    checkReadOnlyMode();
389    Table htable = getTable(table);
390    try {
391      return resultFromHBase(htable.increment(incrementFromThrift(increment)));
392    } catch (IOException e) {
393      throw getTIOError(e);
394    } finally {
395      closeTable(htable);
396    }
397  }
398
399  @Override
400  public TResult append(ByteBuffer table, TAppend append) throws TIOError, TException {
401    checkReadOnlyMode();
402    Table htable = getTable(table);
403    try {
404      return resultFromHBase(htable.append(appendFromThrift(append)));
405    } catch (IOException e) {
406      throw getTIOError(e);
407    } finally {
408      closeTable(htable);
409    }
410  }
411
412  @Override
413  public int openScanner(ByteBuffer table, TScan scan) throws TIOError, TException {
414    Table htable = getTable(table);
415    ResultScanner resultScanner = null;
416    try {
417      resultScanner = htable.getScanner(scanFromThrift(scan));
418    } catch (IOException e) {
419      throw getTIOError(e);
420    } finally {
421      closeTable(htable);
422    }
423    return addScanner(resultScanner);
424  }
425
426  @Override
427  public List<TResult> getScannerRows(int scannerId, int numRows) throws TIOError,
428      TIllegalArgument, TException {
429    ResultScanner scanner = getScanner(scannerId);
430    if (scanner == null) {
431      TIllegalArgument ex = new TIllegalArgument();
432      ex.setMessage("Invalid scanner Id");
433      throw ex;
434    }
435    try {
436      connectionCache.updateConnectionAccessTime();
437      return resultsFromHBase(scanner.next(numRows));
438    } catch (IOException e) {
439      throw getTIOError(e);
440    }
441  }
442
443  @Override
444  public List<TResult> getScannerResults(ByteBuffer table, TScan scan, int numRows)
445      throws TIOError, TException {
446    Table htable = getTable(table);
447    List<TResult> results = null;
448    ResultScanner scanner = null;
449    try {
450      scanner = htable.getScanner(scanFromThrift(scan));
451      results = resultsFromHBase(scanner.next(numRows));
452    } catch (IOException e) {
453      throw getTIOError(e);
454    } finally {
455      if (scanner != null) {
456        scanner.close();
457      }
458      closeTable(htable);
459    }
460    return results;
461  }
462
463
464
465  @Override
466  public void closeScanner(int scannerId) throws TIOError, TIllegalArgument, TException {
467    LOG.debug("scannerClose: id=" + scannerId);
468    ResultScanner scanner = getScanner(scannerId);
469    if (scanner == null) {
470      String message = "scanner ID is invalid";
471      LOG.warn(message);
472      TIllegalArgument ex = new TIllegalArgument();
473      ex.setMessage("Invalid scanner Id");
474      throw ex;
475    }
476    scanner.close();
477    removeScanner(scannerId);
478  }
479
480  @Override
481  public void mutateRow(ByteBuffer table, TRowMutations rowMutations) throws TIOError, TException {
482    checkReadOnlyMode();
483    Table htable = getTable(table);
484    try {
485      htable.mutateRow(rowMutationsFromThrift(rowMutations));
486    } catch (IOException e) {
487      throw getTIOError(e);
488    } finally {
489      closeTable(htable);
490    }
491  }
492
493  @Override
494  public List<THRegionLocation> getAllRegionLocations(ByteBuffer table)
495      throws TIOError, TException {
496    RegionLocator locator = null;
497    try {
498      locator = getLocator(table);
499      return ThriftUtilities.regionLocationsFromHBase(locator.getAllRegionLocations());
500
501    } catch (IOException e) {
502      throw getTIOError(e);
503    } finally {
504      if (locator != null) {
505        try {
506          locator.close();
507        } catch (IOException e) {
508          LOG.warn("Couldn't close the locator.", e);
509        }
510      }
511    }
512  }
513
514  @Override
515  public THRegionLocation getRegionLocation(ByteBuffer table, ByteBuffer row, boolean reload)
516      throws TIOError, TException {
517
518    RegionLocator locator = null;
519    try {
520      locator = getLocator(table);
521      byte[] rowBytes = byteBufferToByteArray(row);
522      HRegionLocation hrl = locator.getRegionLocation(rowBytes, reload);
523      return ThriftUtilities.regionLocationFromHBase(hrl);
524
525    } catch (IOException e) {
526      throw getTIOError(e);
527    } finally {
528      if (locator != null) {
529        try {
530          locator.close();
531        } catch (IOException e) {
532          LOG.warn("Couldn't close the locator.", e);
533        }
534      }
535    }
536  }
537
538  private void checkReadOnlyMode() throws TIOError {
539    if (isReadOnly()) {
540      throw getTIOError(ioe);
541    }
542  }
543
544  private boolean isReadOnly() {
545    return isReadOnly;
546  }
547
548  @Override
549  public TTableDescriptor getTableDescriptor(TTableName table) throws TIOError, TException {
550    try {
551      TableName tableName = ThriftUtilities.tableNameFromThrift(table);
552      TableDescriptor tableDescriptor = connectionCache.getAdmin().getDescriptor(tableName);
553      return tableDescriptorFromHBase(tableDescriptor);
554    } catch (IOException e) {
555      throw getTIOError(e);
556    }
557  }
558
559  @Override
560  public List<TTableDescriptor> getTableDescriptors(List<TTableName> tables)
561      throws TIOError, TException {
562    try {
563      List<TableName> tableNames = ThriftUtilities.tableNamesFromThrift(tables);
564      List<TableDescriptor> tableDescriptors = connectionCache.getAdmin()
565          .listTableDescriptors(tableNames);
566      return tableDescriptorsFromHBase(tableDescriptors);
567    } catch (IOException e) {
568      throw getTIOError(e);
569    }
570  }
571
572  @Override
573  public boolean tableExists(TTableName tTableName) throws TIOError, TException {
574    try {
575      TableName tableName = tableNameFromThrift(tTableName);
576      return connectionCache.getAdmin().tableExists(tableName);
577    } catch (IOException e) {
578      throw getTIOError(e);
579    }
580  }
581
582  @Override
583  public List<TTableDescriptor> getTableDescriptorsByPattern(String regex, boolean includeSysTables)
584      throws TIOError, TException {
585    try {
586      Pattern pattern = (regex == null ? null : Pattern.compile(regex));
587      List<TableDescriptor> tableDescriptors = connectionCache.getAdmin()
588          .listTableDescriptors(pattern, includeSysTables);
589      return tableDescriptorsFromHBase(tableDescriptors);
590    } catch (IOException e) {
591      throw getTIOError(e);
592    }
593  }
594
595  @Override
596  public List<TTableDescriptor> getTableDescriptorsByNamespace(String name)
597      throws TIOError, TException {
598    try {
599      List<TableDescriptor> descriptors = connectionCache.getAdmin()
600          .listTableDescriptorsByNamespace(Bytes.toBytes(name));
601      return tableDescriptorsFromHBase(descriptors);
602    } catch (IOException e) {
603      throw getTIOError(e);
604    }
605  }
606
607  @Override
608  public List<TTableName> getTableNamesByPattern(String regex, boolean includeSysTables)
609      throws TIOError, TException {
610    try {
611      Pattern pattern = (regex == null ? null : Pattern.compile(regex));
612      TableName[] tableNames = connectionCache.getAdmin()
613          .listTableNames(pattern, includeSysTables);
614      return tableNamesFromHBase(tableNames);
615    } catch (IOException e) {
616      throw getTIOError(e);
617    }
618  }
619
620  @Override
621  public List<TTableName> getTableNamesByNamespace(String name) throws TIOError, TException {
622    try {
623      TableName[] tableNames = connectionCache.getAdmin().listTableNamesByNamespace(name);
624      return tableNamesFromHBase(tableNames);
625    } catch (IOException e) {
626      throw getTIOError(e);
627    }
628  }
629
630  @Override
631  public void createTable(TTableDescriptor desc, List<ByteBuffer> splitKeys)
632      throws TIOError, TException {
633    try {
634      TableDescriptor descriptor = tableDescriptorFromThrift(desc);
635      byte[][] split = splitKeyFromThrift(splitKeys);
636      connectionCache.getAdmin().createTable(descriptor, split);
637    } catch (IOException e) {
638      throw getTIOError(e);
639    }
640  }
641
642  @Override
643  public void deleteTable(TTableName tableName) throws TIOError, TException {
644    try {
645      TableName table = tableNameFromThrift(tableName);
646      connectionCache.getAdmin().deleteTable(table);
647    } catch (IOException e) {
648      throw getTIOError(e);
649    }
650  }
651
652  @Override
653  public void truncateTable(TTableName tableName, boolean preserveSplits)
654      throws TIOError, TException {
655    try {
656      TableName table = tableNameFromThrift(tableName);
657      connectionCache.getAdmin().truncateTable(table, preserveSplits);
658    } catch (IOException e) {
659      throw getTIOError(e);
660    }
661  }
662
663  @Override
664  public void enableTable(TTableName tableName) throws TIOError, TException {
665    try {
666      TableName table = tableNameFromThrift(tableName);
667      connectionCache.getAdmin().enableTable(table);
668    } catch (IOException e) {
669      throw getTIOError(e);
670    }
671  }
672
673  @Override
674  public void disableTable(TTableName tableName) throws TIOError, TException {
675    try {
676      TableName table = tableNameFromThrift(tableName);
677      connectionCache.getAdmin().disableTable(table);
678    } catch (IOException e) {
679      throw getTIOError(e);
680    }
681  }
682
683  @Override
684  public boolean isTableEnabled(TTableName tableName) throws TIOError, TException {
685    try {
686      TableName table = tableNameFromThrift(tableName);
687      return connectionCache.getAdmin().isTableEnabled(table);
688    } catch (IOException e) {
689      throw getTIOError(e);
690    }
691  }
692
693  @Override
694  public boolean isTableDisabled(TTableName tableName) throws TIOError, TException {
695    try {
696      TableName table = tableNameFromThrift(tableName);
697      return connectionCache.getAdmin().isTableDisabled(table);
698    } catch (IOException e) {
699      throw getTIOError(e);
700    }
701  }
702
703  @Override
704  public boolean isTableAvailable(TTableName tableName) throws TIOError, TException {
705    try {
706      TableName table = tableNameFromThrift(tableName);
707      return connectionCache.getAdmin().isTableAvailable(table);
708    } catch (IOException e) {
709      throw getTIOError(e);
710    }
711  }
712
713  @Override
714  public boolean isTableAvailableWithSplit(TTableName tableName, List<ByteBuffer> splitKeys)
715      throws TIOError, TException {
716    try {
717      TableName table = tableNameFromThrift(tableName);
718      byte[][] split = splitKeyFromThrift(splitKeys);
719      return connectionCache.getAdmin().isTableAvailable(table, split);
720    } catch (IOException e) {
721      throw getTIOError(e);
722    }
723  }
724
725  @Override
726  public void addColumnFamily(TTableName tableName, TColumnFamilyDescriptor column)
727      throws TIOError, TException {
728    try {
729      TableName table = tableNameFromThrift(tableName);
730      ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorFromThrift(column);
731      connectionCache.getAdmin().addColumnFamily(table, columnFamilyDescriptor);
732    } catch (IOException e) {
733      throw getTIOError(e);
734    }
735  }
736
737  @Override
738  public void deleteColumnFamily(TTableName tableName, ByteBuffer column)
739      throws TIOError, TException {
740    try {
741      TableName table = tableNameFromThrift(tableName);
742      connectionCache.getAdmin().deleteColumnFamily(table, column.array());
743    } catch (IOException e) {
744      throw getTIOError(e);
745    }
746  }
747
748  @Override
749  public void modifyColumnFamily(TTableName tableName, TColumnFamilyDescriptor column)
750      throws TIOError, TException {
751    try {
752      TableName table = tableNameFromThrift(tableName);
753      ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorFromThrift(column);
754      connectionCache.getAdmin().modifyColumnFamily(table, columnFamilyDescriptor);
755    } catch (IOException e) {
756      throw getTIOError(e);
757    }
758  }
759
760  @Override
761  public void modifyTable(TTableDescriptor desc) throws TIOError, TException {
762    try {
763      TableDescriptor descriptor = tableDescriptorFromThrift(desc);
764      connectionCache.getAdmin().modifyTable(descriptor);
765    } catch (IOException e) {
766      throw getTIOError(e);
767    }
768  }
769
770  @Override
771  public void createNamespace(TNamespaceDescriptor namespaceDesc) throws TIOError, TException {
772    try {
773      NamespaceDescriptor descriptor = namespaceDescriptorFromThrift(namespaceDesc);
774      connectionCache.getAdmin().createNamespace(descriptor);
775    } catch (IOException e) {
776      throw getTIOError(e);
777    }
778  }
779
780  @Override
781  public void modifyNamespace(TNamespaceDescriptor namespaceDesc) throws TIOError, TException {
782    try {
783      NamespaceDescriptor descriptor = namespaceDescriptorFromThrift(namespaceDesc);
784      connectionCache.getAdmin().modifyNamespace(descriptor);
785    } catch (IOException e) {
786      throw getTIOError(e);
787    }
788  }
789
790  @Override
791  public void deleteNamespace(String name) throws TIOError, TException {
792    try {
793      connectionCache.getAdmin().deleteNamespace(name);
794    } catch (IOException e) {
795      throw getTIOError(e);
796    }
797  }
798
799  @Override
800  public TNamespaceDescriptor getNamespaceDescriptor(String name) throws TIOError, TException {
801    try {
802      NamespaceDescriptor descriptor = connectionCache.getAdmin().getNamespaceDescriptor(name);
803      return namespaceDescriptorFromHBase(descriptor);
804    } catch (IOException e) {
805      throw getTIOError(e);
806    }
807  }
808
809  @Override
810  public List<String> listNamespaces() throws TIOError, TException {
811    try {
812      String[] namespaces = connectionCache.getAdmin().listNamespaces();
813      List<String> result = new ArrayList<>(namespaces.length);
814      for (String ns: namespaces) {
815        result.add(ns);
816      }
817      return result;
818    } catch (IOException e) {
819      throw getTIOError(e);
820    }
821  }
822
823  @Override
824  public TThriftServerType getThriftServerType() {
825    return TThriftServerType.TWO;
826  }
827
828  @Override
829  public List<TOnlineLogRecord> getSlowLogResponses(Set<TServerName> tServerNames,
830      TLogQueryFilter tLogQueryFilter) throws TIOError, TException {
831    try {
832      Set<ServerName> serverNames = ThriftUtilities.getServerNamesFromThrift(tServerNames);
833      LogQueryFilter logQueryFilter =
834        ThriftUtilities.getSlowLogQueryFromThrift(tLogQueryFilter);
835      List<OnlineLogRecord> onlineLogRecords =
836        connectionCache.getAdmin().getSlowLogResponses(serverNames, logQueryFilter);
837      return ThriftUtilities.getSlowLogRecordsFromHBase(onlineLogRecords);
838    } catch (IOException e) {
839      throw getTIOError(e);
840    }
841  }
842
843  @Override
844  public List<Boolean> clearSlowLogResponses(Set<TServerName> tServerNames)
845      throws TIOError, TException {
846    Set<ServerName> serverNames = ThriftUtilities.getServerNamesFromThrift(tServerNames);
847    try {
848      return connectionCache.getAdmin().clearSlowLogResponses(serverNames);
849    } catch (IOException e) {
850      throw getTIOError(e);
851    }
852  }
853
854  @Override
855  public List<TNamespaceDescriptor> listNamespaceDescriptors() throws TIOError, TException {
856    try {
857      NamespaceDescriptor[] descriptors = connectionCache.getAdmin().listNamespaceDescriptors();
858      return namespaceDescriptorsFromHBase(descriptors);
859    } catch (IOException e) {
860      throw getTIOError(e);
861    }
862  }
863}