View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import static org.apache.hadoop.hbase.util.Bytes.getBytes;
22  
23  import java.io.IOException;
24  import java.nio.ByteBuffer;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.hadoop.classification.InterfaceAudience;
31  import org.apache.hadoop.conf.Configuration;
32  import org.apache.hadoop.hbase.HRegionLocation;
33  import org.apache.hadoop.hbase.KeyValue;
34  import org.apache.hadoop.hbase.NotServingRegionException;
35  import org.apache.hadoop.hbase.client.Get;
36  import org.apache.hadoop.hbase.client.HTable;
37  import org.apache.hadoop.hbase.client.Result;
38  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
39  import org.apache.hadoop.hbase.thrift.ThriftServerRunner;
40  import org.apache.hadoop.hbase.thrift.ThriftUtilities;
41  import org.apache.hadoop.hbase.thrift.generated.IOError;
42  import org.apache.hadoop.hbase.thrift.generated.TRowResult;
43  
44  /**
45   * HRegionThriftServer - this class starts up a Thrift server in the same
46   * JVM where the RegionServer is running. It inherits most of the
47   * functionality from the standard ThriftServer. This is good because
48   * we can maintain compatibility with applications that use the
49   * standard Thrift interface. For performance reasons, we can override
50   * methods to directly invoke calls into the HRegionServer and avoid the hop.
51   * <p>
52   * This can be enabled with <i>hbase.regionserver.export.thrift</i> set to true.
53   */
54  @InterfaceAudience.Private
55  public class HRegionThriftServer extends Thread {
56  
57    public static final Log LOG = LogFactory.getLog(HRegionThriftServer.class);
58  
59    private final HRegionServer rs;
60    private final ThriftServerRunner serverRunner;
61  
62    /**
63     * Create an instance of the glue object that connects the
64     * RegionServer with the standard ThriftServer implementation
65     */
66    HRegionThriftServer(HRegionServer regionServer, Configuration conf)
67        throws IOException {
68      super("Region Thrift Server");
69      this.rs = regionServer;
70      this.serverRunner =
71          new ThriftServerRunner(conf, new HBaseHandlerRegion(conf));
72    }
73  
74    /**
75     * Stop ThriftServer
76     */
77    void shutdown() {
78      serverRunner.shutdown();
79    }
80  
81    @Override
82    public void run() {
83      serverRunner.run();
84    }
85  
86    /**
87     * Inherit the Handler from the standard ThriftServerRunner. This allows us
88     * to use the default implementation for most calls. We override certain calls
89     * for performance reasons
90     */
91    private class HBaseHandlerRegion extends ThriftServerRunner.HBaseHandler {
92  
93      /**
94       * Whether requests should be redirected to other RegionServers if the
95       * specified region is not hosted by this RegionServer.
96       */
97      private boolean redirect;
98  
99      HBaseHandlerRegion(final Configuration conf) throws IOException {
100       super(conf);
101       initialize(conf);
102     }
103 
104     /**
105      * Read and initialize config parameters
106      */
107     private void initialize(Configuration conf) {
108       this.redirect = conf.getBoolean("hbase.regionserver.thrift.redirect",
109           false);
110     }
111 
112     // TODO: Override more methods to short-circuit for performance
113 
114     /**
115      * Get a record. Short-circuit to get better performance.
116      */
117     @Override
118     public List<TRowResult> getRowWithColumnsTs(ByteBuffer tableName,
119                                                 ByteBuffer rowb,
120                                                 List<ByteBuffer> columns,
121                                                 long timestamp,
122       Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
123       try {
124         byte[] row = getBytes(rowb);
125 
126         HTable table = getTable(getBytes(tableName));
127         HRegionLocation location = table.getRegionLocation(row, false);
128         byte[] regionName = location.getRegionInfo().getRegionName();
129 
130         if (columns == null) {
131           Get get = new Get(row);
132           get.setTimeRange(Long.MIN_VALUE, timestamp);
133           Result result = ProtobufUtil.get(rs, regionName, get);
134           return ThriftUtilities.rowResultFromHBase(result);
135         }
136         Get get = new Get(row);
137         for(ByteBuffer column : columns) {
138           byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
139           if (famAndQf.length == 1) {
140             get.addFamily(famAndQf[0]);
141           } else {
142             get.addColumn(famAndQf[0], famAndQf[1]);
143           }
144         }
145         get.setTimeRange(Long.MIN_VALUE, timestamp);
146         Result result = ProtobufUtil.get(rs, regionName, get);
147         return ThriftUtilities.rowResultFromHBase(result);
148       } catch (NotServingRegionException e) {
149         if (!redirect) {
150           LOG.warn(e.getMessage(), e);
151           throw new IOError(e.getMessage());
152         }
153         LOG.debug("ThriftServer redirecting getRowWithColumnsTs");
154         return super.getRowWithColumnsTs(tableName, rowb, columns, timestamp,
155                                          attributes);
156       } catch (IOException e) {
157         LOG.warn(e.getMessage(), e);
158         throw new IOError(e.getMessage());
159       }
160     }
161   }
162 }