@Override
  public TRegionInfo getRegionInfo(ByteBuffer searchRow) throws IOError {
    try {
      byte[] row = getBytes(searchRow);
      Result startRowResult =
        getReverseScanResult(TableName.META_TABLE_NAME.getName(), row, HConstants.CATALOG_FAMILY);

      if (startRowResult == null) {
        throw new IOException(
          "Cannot find row in " + TableName.META_TABLE_NAME + ", row=" + Bytes.toStringBinary(row));
      }

      // find region start and end keys
      RegionInfo regionInfo = CatalogFamilyFormat.getRegionInfo(startRowResult);
      if (regionInfo == null) {
        throw new IOException("RegionInfo REGIONINFO was null or " + " empty in Meta for row="
          + Bytes.toStringBinary(row));
      }
      TRegionInfo region = new TRegionInfo();
      region.setStartKey(regionInfo.getStartKey());
      region.setEndKey(regionInfo.getEndKey());
      region.id = regionInfo.getRegionId();
      region.setName(regionInfo.getRegionName());
      region.version = HREGION_VERSION; // version not used anymore, PB encoding used.

      // find region assignment to server
      ServerName serverName = CatalogFamilyFormat.getServerName(startRowResult, 0);
      if (serverName != null) {
        region.setServerName(Bytes.toBytes(serverName.getHostname()));
        region.port = serverName.getPort();
      }
      return region;
    } catch (IOException e) {
      LOG.warn(e.getMessage(), e);
      throw getIOError(e);
    }
  }
Note: this internal interface is slightly different from public APIs in regard to handling of
the qualifier. Here we differ from the public Java API in that null != byte[0]. Rather, we
respect qual == null as a request for the entire column family. The caller (
{@link #getVerTs(ByteBuffer, ByteBuffer, ByteBuffer, long, int, Map)}) interface IS consistent
in that the column is parse like normal.
hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift/ThriftHBaseServiceHandler.java