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