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.thrift2;
20  
21  import java.io.IOException;
22  import java.net.InetAddress;
23  import java.net.InetSocketAddress;
24  import java.net.UnknownHostException;
25  import java.security.PrivilegedAction;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.concurrent.ExecutorService;
30  import java.util.concurrent.LinkedBlockingQueue;
31  import java.util.concurrent.SynchronousQueue;
32  import java.util.concurrent.ThreadPoolExecutor;
33  import java.util.concurrent.TimeUnit;
34  
35  import javax.security.auth.callback.Callback;
36  import javax.security.auth.callback.UnsupportedCallbackException;
37  import javax.security.sasl.AuthorizeCallback;
38  import javax.security.sasl.Sasl;
39  import javax.security.sasl.SaslServer;
40  
41  import org.apache.commons.cli.CommandLine;
42  import org.apache.commons.cli.CommandLineParser;
43  import org.apache.commons.cli.HelpFormatter;
44  import org.apache.commons.cli.Option;
45  import org.apache.commons.cli.OptionGroup;
46  import org.apache.commons.cli.Options;
47  import org.apache.commons.cli.ParseException;
48  import org.apache.commons.cli.PosixParser;
49  import org.apache.commons.logging.Log;
50  import org.apache.commons.logging.LogFactory;
51  import org.apache.hadoop.conf.Configuration;
52  import org.apache.hadoop.hbase.HBaseConfiguration;
53  import org.apache.hadoop.hbase.HBaseInterfaceAudience;
54  import org.apache.hadoop.hbase.classification.InterfaceAudience;
55  import org.apache.hadoop.hbase.filter.ParseFilter;
56  import org.apache.hadoop.hbase.http.InfoServer;
57  import org.apache.hadoop.hbase.security.SaslUtil;
58  import org.apache.hadoop.hbase.security.SecurityUtil;
59  import org.apache.hadoop.hbase.security.UserProvider;
60  import org.apache.hadoop.hbase.thrift.CallQueue;
61  import org.apache.hadoop.hbase.thrift.CallQueue.Call;
62  import org.apache.hadoop.hbase.thrift.THBaseThreadPoolExecutor;
63  import org.apache.hadoop.hbase.thrift.ThriftMetrics;
64  import org.apache.hadoop.hbase.thrift2.generated.THBaseService;
65  import org.apache.hadoop.hbase.util.DNS;
66  import org.apache.hadoop.hbase.util.Strings;
67  import org.apache.hadoop.security.SaslRpcServer.SaslGssCallbackHandler;
68  import org.apache.hadoop.security.UserGroupInformation;
69  import org.apache.hadoop.util.GenericOptionsParser;
70  import org.apache.thrift.TException;
71  import org.apache.thrift.TProcessor;
72  import org.apache.thrift.protocol.TBinaryProtocol;
73  import org.apache.thrift.protocol.TCompactProtocol;
74  import org.apache.thrift.protocol.TProtocol;
75  import org.apache.thrift.protocol.TProtocolFactory;
76  import org.apache.thrift.server.THsHaServer;
77  import org.apache.thrift.server.TNonblockingServer;
78  import org.apache.thrift.server.TServer;
79  import org.apache.thrift.server.TThreadPoolServer;
80  import org.apache.thrift.server.TThreadedSelectorServer;
81  import org.apache.thrift.transport.TFramedTransport;
82  import org.apache.thrift.transport.TNonblockingServerSocket;
83  import org.apache.thrift.transport.TNonblockingServerTransport;
84  import org.apache.thrift.transport.TSaslServerTransport;
85  import org.apache.thrift.transport.TServerSocket;
86  import org.apache.thrift.transport.TServerTransport;
87  import org.apache.thrift.transport.TTransportException;
88  import org.apache.thrift.transport.TTransportFactory;
89  
90  import com.google.common.util.concurrent.ThreadFactoryBuilder;
91  
92  /**
93   * ThriftServer - this class starts up a Thrift server which implements the HBase API specified in the
94   * HbaseClient.thrift IDL file.
95   */
96  @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS)
97  @SuppressWarnings({ "rawtypes", "unchecked" })
98  public class ThriftServer {
99    private static final Log log = LogFactory.getLog(ThriftServer.class);
100 
101   /**
102    * Thrift quality of protection configuration key. Valid values can be:
103    * privacy: authentication, integrity and confidentiality checking
104    * integrity: authentication and integrity checking
105    * authentication: authentication only
106    *
107    * This is used to authenticate the callers and support impersonation.
108    * The thrift server and the HBase cluster must run in secure mode.
109    */
110   static final String THRIFT_QOP_KEY = "hbase.thrift.security.qop";
111 
112   static final String BACKLOG_CONF_KEY = "hbase.regionserver.thrift.backlog";
113 
114   public static final int DEFAULT_LISTEN_PORT = 9090;
115 
116   private static final String READ_TIMEOUT_OPTION = "readTimeout";
117 
118   /**
119    * Amount of time in milliseconds before a server thread will timeout
120    * waiting for client to send data on a connected socket. Currently,
121    * applies only to TBoundedThreadPoolServer
122    */
123   public static final String THRIFT_SERVER_SOCKET_READ_TIMEOUT_KEY =
124     "hbase.thrift.server.socket.read.timeout";
125   public static final int THRIFT_SERVER_SOCKET_READ_TIMEOUT_DEFAULT = 60000;
126 
127   public ThriftServer() {
128   }
129 
130   private static void printUsage() {
131     HelpFormatter formatter = new HelpFormatter();
132     formatter.printHelp("Thrift", null, getOptions(),
133         "To start the Thrift server run 'bin/hbase-daemon.sh start thrift2'\n" +
134             "To shutdown the thrift server run 'bin/hbase-daemon.sh stop thrift2' or" +
135             " send a kill signal to the thrift server pid",
136         true);
137   }
138 
139   private static Options getOptions() {
140     Options options = new Options();
141     options.addOption("b", "bind", true,
142         "Address to bind the Thrift server to. [default: 0.0.0.0]");
143     options.addOption("p", "port", true, "Port to bind to [default: " + DEFAULT_LISTEN_PORT + "]");
144     options.addOption("f", "framed", false, "Use framed transport");
145     options.addOption("c", "compact", false, "Use the compact protocol");
146     options.addOption("w", "workers", true, "How many worker threads to use.");
147     options.addOption("s", "selectors", true, "How many selector threads to use.");
148     options.addOption("q", "callQueueSize", true,
149       "Max size of request queue (unbounded by default)");
150     options.addOption("h", "help", false, "Print help information");
151     options.addOption(null, "infoport", true, "Port for web UI");
152     options.addOption("t", READ_TIMEOUT_OPTION, true,
153       "Amount of time in milliseconds before a server thread will timeout " +
154       "waiting for client to send data on a connected socket. Currently, " +
155       "only applies to TBoundedThreadPoolServer");
156     OptionGroup servers = new OptionGroup();
157     servers.addOption(
158         new Option("nonblocking", false,
159             "Use the TNonblockingServer. This implies the framed transport."));
160     servers.addOption(new Option("hsha", false,
161         "Use the THsHaServer. This implies the framed transport."));
162     servers.addOption(new Option("selector", false,
163         "Use the TThreadedSelectorServer. This implies the framed transport."));
164     servers.addOption(new Option("threadpool", false,
165         "Use the TThreadPoolServer. This is the default."));
166     options.addOptionGroup(servers);
167     return options;
168   }
169 
170   private static CommandLine parseArguments(Configuration conf, Options options, String[] args)
171       throws ParseException, IOException {
172     GenericOptionsParser genParser = new GenericOptionsParser(conf, args);
173     String[] remainingArgs = genParser.getRemainingArgs();
174     CommandLineParser parser = new PosixParser();
175     return parser.parse(options, remainingArgs);
176   }
177 
178   private static TProtocolFactory getTProtocolFactory(boolean isCompact) {
179     if (isCompact) {
180       log.debug("Using compact protocol");
181       return new TCompactProtocol.Factory();
182     } else {
183       log.debug("Using binary protocol");
184       return new TBinaryProtocol.Factory();
185     }
186   }
187 
188   private static TTransportFactory getTTransportFactory(
189       SaslUtil.QualityOfProtection qop, String name, String host,
190       boolean framed, int frameSize) {
191     if (framed) {
192       if (qop != null) {
193         throw new RuntimeException("Thrift server authentication"
194           + " doesn't work with framed transport yet");
195       }
196       log.debug("Using framed transport");
197       return new TFramedTransport.Factory(frameSize);
198     } else if (qop == null) {
199       return new TTransportFactory();
200     } else {
201       Map<String, String> saslProperties = new HashMap<String, String>();
202       saslProperties.put(Sasl.QOP, qop.getSaslQop());
203       saslProperties.put(Sasl.SERVER_AUTH, "true");
204       TSaslServerTransport.Factory saslFactory = new TSaslServerTransport.Factory();
205       saslFactory.addServerDefinition("GSSAPI", name, host, saslProperties,
206         new SaslGssCallbackHandler() {
207           @Override
208           public void handle(Callback[] callbacks)
209               throws UnsupportedCallbackException {
210             AuthorizeCallback ac = null;
211             for (Callback callback : callbacks) {
212               if (callback instanceof AuthorizeCallback) {
213                 ac = (AuthorizeCallback) callback;
214               } else {
215                 throw new UnsupportedCallbackException(callback,
216                     "Unrecognized SASL GSSAPI Callback");
217               }
218             }
219             if (ac != null) {
220               String authid = ac.getAuthenticationID();
221               String authzid = ac.getAuthorizationID();
222               if (!authid.equals(authzid)) {
223                 ac.setAuthorized(false);
224               } else {
225                 ac.setAuthorized(true);
226                 String userName = SecurityUtil.getUserFromPrincipal(authzid);
227                 log.info("Effective user: " + userName);
228                 ac.setAuthorizedID(userName);
229               }
230             }
231           }
232         });
233       return saslFactory;
234     }
235   }
236 
237   /*
238    * If bindValue is null, we don't bind.
239    */
240   private static InetSocketAddress bindToPort(String bindValue, int listenPort)
241       throws UnknownHostException {
242     try {
243       if (bindValue == null) {
244         return new InetSocketAddress(listenPort);
245       } else {
246         return new InetSocketAddress(InetAddress.getByName(bindValue), listenPort);
247       }
248     } catch (UnknownHostException e) {
249       throw new RuntimeException("Could not bind to provided ip address", e);
250     }
251   }
252 
253   private static TServer getTNonBlockingServer(TProtocolFactory protocolFactory, TProcessor processor,
254       TTransportFactory transportFactory, InetSocketAddress inetSocketAddress) throws TTransportException {
255     TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(inetSocketAddress);
256     log.info("starting HBase Nonblocking Thrift server on " + inetSocketAddress.toString());
257     TNonblockingServer.Args serverArgs = new TNonblockingServer.Args(serverTransport);
258     serverArgs.processor(processor);
259     serverArgs.transportFactory(transportFactory);
260     serverArgs.protocolFactory(protocolFactory);
261     return new TNonblockingServer(serverArgs);
262   }
263 
264   private static TServer getTHsHaServer(TProtocolFactory protocolFactory,
265       TProcessor processor, TTransportFactory transportFactory,
266       int workerThreads, int maxCallQueueSize,
267       InetSocketAddress inetSocketAddress, ThriftMetrics metrics)
268       throws TTransportException {
269     TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(inetSocketAddress);
270     log.info("starting HBase HsHA Thrift server on " + inetSocketAddress.toString());
271     THsHaServer.Args serverArgs = new THsHaServer.Args(serverTransport);
272     if (workerThreads > 0) {
273       // Could support the min & max threads, avoiding to preserve existing functionality.
274       serverArgs.minWorkerThreads(workerThreads).maxWorkerThreads(workerThreads);
275     }
276     ExecutorService executorService = createExecutor(
277         workerThreads, maxCallQueueSize, metrics);
278     serverArgs.executorService(executorService);
279     serverArgs.processor(processor);
280     serverArgs.transportFactory(transportFactory);
281     serverArgs.protocolFactory(protocolFactory);
282     return new THsHaServer(serverArgs);
283   }
284 
285   private static TServer getTThreadedSelectorServer(TProtocolFactory protocolFactory,
286       TProcessor processor, TTransportFactory transportFactory,
287       int workerThreads, int selectorThreads, int maxCallQueueSize,
288       InetSocketAddress inetSocketAddress, ThriftMetrics metrics)
289       throws TTransportException {
290     TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(inetSocketAddress);
291     log.info("starting HBase ThreadedSelector Thrift server on " + inetSocketAddress.toString());
292     TThreadedSelectorServer.Args serverArgs = new TThreadedSelectorServer.Args(serverTransport);
293     if (workerThreads > 0) {
294       serverArgs.workerThreads(workerThreads);
295     }
296     if (selectorThreads > 0) {
297       serverArgs.selectorThreads(selectorThreads);
298     }
299 
300     ExecutorService executorService = createExecutor(workerThreads, maxCallQueueSize, metrics);
301     serverArgs.executorService(executorService);
302     serverArgs.processor(processor);
303     serverArgs.transportFactory(transportFactory);
304     serverArgs.protocolFactory(protocolFactory);
305     return new TThreadedSelectorServer(serverArgs);
306   }
307 
308   private static ExecutorService createExecutor(
309       int workerThreads, int maxCallQueueSize, ThriftMetrics metrics) {
310     CallQueue callQueue;
311     if (maxCallQueueSize > 0) {
312       callQueue = new CallQueue(new LinkedBlockingQueue<Call>(maxCallQueueSize), metrics);
313     } else {
314       callQueue = new CallQueue(new LinkedBlockingQueue<Call>(), metrics);
315     }
316 
317     ThreadFactoryBuilder tfb = new ThreadFactoryBuilder();
318     tfb.setDaemon(true);
319     tfb.setNameFormat("thrift2-worker-%d");
320     ThreadPoolExecutor pool = new THBaseThreadPoolExecutor(workerThreads, workerThreads,
321             Long.MAX_VALUE, TimeUnit.SECONDS, callQueue, tfb.build(), metrics);
322     pool.prestartAllCoreThreads();
323     return pool;
324   }
325 
326   private static TServer getTThreadPoolServer(TProtocolFactory protocolFactory,
327                                               TProcessor processor,
328                                               TTransportFactory transportFactory,
329                                               int workerThreads,
330                                               InetSocketAddress inetSocketAddress,
331                                               int backlog,
332                                               int clientTimeout,
333                                               ThriftMetrics metrics)
334       throws TTransportException {
335     TServerTransport serverTransport = new TServerSocket(
336                                            new TServerSocket.ServerSocketTransportArgs().
337                                                bindAddr(inetSocketAddress).backlog(backlog).
338                                                clientTimeout(clientTimeout));
339     log.info("starting HBase ThreadPool Thrift server on " + inetSocketAddress.toString());
340     TThreadPoolServer.Args serverArgs = new TThreadPoolServer.Args(serverTransport);
341     serverArgs.processor(processor);
342     serverArgs.transportFactory(transportFactory);
343     serverArgs.protocolFactory(protocolFactory);
344     if (workerThreads > 0) {
345       serverArgs.maxWorkerThreads(workerThreads);
346     }
347     ThreadPoolExecutor executor = new THBaseThreadPoolExecutor(serverArgs.minWorkerThreads,
348         serverArgs.maxWorkerThreads, serverArgs.stopTimeoutVal, TimeUnit.SECONDS,
349         new SynchronousQueue<Runnable>(), metrics);
350     serverArgs.executorService(executor);
351 
352     return new TThreadPoolServer(serverArgs);
353   }
354 
355   /**
356    * Adds the option to pre-load filters at startup.
357    *
358    * @param conf  The current configuration instance.
359    */
360   protected static void registerFilters(Configuration conf) {
361     String[] filters = conf.getStrings("hbase.thrift.filters");
362     if(filters != null) {
363       for(String filterClass: filters) {
364         String[] filterPart = filterClass.split(":");
365         if(filterPart.length != 2) {
366           log.warn("Invalid filter specification " + filterClass + " - skipping");
367         } else {
368           ParseFilter.registerFilter(filterPart[0], filterPart[1]);
369         }
370       }
371     }
372   }
373 
374   /**
375    * Start up the Thrift2 server.
376    *
377    * @param args
378    */
379   public static void main(String[] args) throws Exception {
380     TServer server = null;
381     Options options = getOptions();
382     Configuration conf = HBaseConfiguration.create();
383     CommandLine cmd = parseArguments(conf, options, args);
384     int workerThreads = 0;
385     int selectorThreads = 0;
386     int maxCallQueueSize = -1; // use unbounded queue by default
387 
388     /**
389      * This is to please both bin/hbase and bin/hbase-daemon. hbase-daemon provides "start" and "stop" arguments hbase
390      * should print the help if no argument is provided
391      */
392     List<?> argList = cmd.getArgList();
393     if (cmd.hasOption("help") || !argList.contains("start") || argList.contains("stop")) {
394       printUsage();
395       System.exit(1);
396     }
397 
398     // Get address to bind
399     String bindAddress;
400     if (cmd.hasOption("bind")) {
401       bindAddress = cmd.getOptionValue("bind");
402       conf.set("hbase.thrift.info.bindAddress", bindAddress);
403     } else {
404       bindAddress = conf.get("hbase.thrift.info.bindAddress");
405     }
406 
407     // Get read timeout
408     int readTimeout = THRIFT_SERVER_SOCKET_READ_TIMEOUT_DEFAULT;
409     if (cmd.hasOption(READ_TIMEOUT_OPTION)) {
410       try {
411         readTimeout = Integer.parseInt(cmd.getOptionValue(READ_TIMEOUT_OPTION));
412       } catch (NumberFormatException e) {
413         throw new RuntimeException("Could not parse the value provided for the timeout option", e);
414       }
415     } else {
416       readTimeout = conf.getInt(THRIFT_SERVER_SOCKET_READ_TIMEOUT_KEY,
417         THRIFT_SERVER_SOCKET_READ_TIMEOUT_DEFAULT);
418     }
419 
420     // Get port to bind to
421     int listenPort = 0;
422     try {
423       if (cmd.hasOption("port")) {
424         listenPort = Integer.parseInt(cmd.getOptionValue("port"));
425       } else {
426         listenPort = conf.getInt("hbase.regionserver.thrift.port", DEFAULT_LISTEN_PORT);
427       }
428     } catch (NumberFormatException e) {
429       throw new RuntimeException("Could not parse the value provided for the port option", e);
430     }
431 
432     // Thrift's implementation uses '0' as a placeholder for 'use the default.'
433     int backlog = conf.getInt(BACKLOG_CONF_KEY, 0);
434 
435     // Local hostname and user name,
436     // used only if QOP is configured.
437     String host = null;
438     String name = null;
439 
440     UserProvider userProvider = UserProvider.instantiate(conf);
441     // login the server principal (if using secure Hadoop)
442     boolean securityEnabled = userProvider.isHadoopSecurityEnabled()
443       && userProvider.isHBaseSecurityEnabled();
444     if (securityEnabled) {
445       host = Strings.domainNamePointerToHostName(DNS.getDefaultHost(
446         conf.get("hbase.thrift.dns.interface", "default"),
447         conf.get("hbase.thrift.dns.nameserver", "default")));
448       userProvider.login("hbase.thrift.keytab.file",
449         "hbase.thrift.kerberos.principal", host);
450     }
451 
452     UserGroupInformation realUser = userProvider.getCurrent().getUGI();
453     String stringQop = conf.get(THRIFT_QOP_KEY);
454     SaslUtil.QualityOfProtection qop = null;
455     if (stringQop != null) {
456       qop = SaslUtil.getQop(stringQop);
457       if (!securityEnabled) {
458         throw new IOException("Thrift server must"
459           + " run in secure mode to support authentication");
460       }
461       // Extract the name from the principal
462       name = SecurityUtil.getUserFromPrincipal(
463         conf.get("hbase.thrift.kerberos.principal"));
464     }
465 
466     boolean nonblocking = cmd.hasOption("nonblocking");
467     boolean hsha = cmd.hasOption("hsha");
468     boolean selector = cmd.hasOption("selector");
469 
470     ThriftMetrics metrics = new ThriftMetrics(conf, ThriftMetrics.ThriftServerType.TWO);
471 
472     String implType = "threadpool";
473     if (nonblocking) {
474       implType = "nonblocking";
475     } else if (hsha) {
476       implType = "hsha";
477     } else if (selector) {
478       implType = "selector";
479     }
480 
481     conf.set("hbase.regionserver.thrift.server.type", implType);
482     conf.setInt("hbase.regionserver.thrift.port", listenPort);
483     registerFilters(conf);
484 
485     // Construct correct ProtocolFactory
486     boolean compact = cmd.hasOption("compact") ||
487         conf.getBoolean("hbase.regionserver.thrift.compact", false);
488     TProtocolFactory protocolFactory = getTProtocolFactory(compact);
489     final ThriftHBaseServiceHandler hbaseHandler =
490       new ThriftHBaseServiceHandler(conf, userProvider);
491     THBaseService.Iface handler =
492       ThriftHBaseServiceHandler.newInstance(hbaseHandler, metrics);
493     final THBaseService.Processor p = new THBaseService.Processor(handler);
494     conf.setBoolean("hbase.regionserver.thrift.compact", compact);
495     TProcessor processor = p;
496 
497     boolean framed = cmd.hasOption("framed") ||
498         conf.getBoolean("hbase.regionserver.thrift.framed", false) || nonblocking || hsha;
499     TTransportFactory transportFactory = getTTransportFactory(qop, name, host, framed,
500         conf.getInt("hbase.regionserver.thrift.framed.max_frame_size_in_mb", 2) * 1024 * 1024);
501     InetSocketAddress inetSocketAddress = bindToPort(bindAddress, listenPort);
502     conf.setBoolean("hbase.regionserver.thrift.framed", framed);
503     if (qop != null) {
504       // Create a processor wrapper, to get the caller
505       processor = new TProcessor() {
506         @Override
507         public boolean process(TProtocol inProt,
508             TProtocol outProt) throws TException {
509           TSaslServerTransport saslServerTransport =
510             (TSaslServerTransport)inProt.getTransport();
511           SaslServer saslServer = saslServerTransport.getSaslServer();
512           String principal = saslServer.getAuthorizationID();
513           hbaseHandler.setEffectiveUser(principal);
514           return p.process(inProt, outProt);
515         }
516       };
517     }
518 
519     if (cmd.hasOption("w")) {
520       workerThreads = Integer.parseInt(cmd.getOptionValue("w"));
521     }
522     if (cmd.hasOption("s")) {
523       selectorThreads = Integer.parseInt(cmd.getOptionValue("s"));
524     }
525     if (cmd.hasOption("q")) {
526       maxCallQueueSize = Integer.parseInt(cmd.getOptionValue("q"));
527     }
528 
529     // check for user-defined info server port setting, if so override the conf
530     try {
531       if (cmd.hasOption("infoport")) {
532         String val = cmd.getOptionValue("infoport");
533         conf.setInt("hbase.thrift.info.port", Integer.parseInt(val));
534         log.debug("Web UI port set to " + val);
535       }
536     } catch (NumberFormatException e) {
537       log.error("Could not parse the value provided for the infoport option", e);
538       printUsage();
539       System.exit(1);
540     }
541 
542     // Put up info server.
543     int port = conf.getInt("hbase.thrift.info.port", 9095);
544     if (port >= 0) {
545       conf.setLong("startcode", System.currentTimeMillis());
546       String a = conf.get("hbase.thrift.info.bindAddress", "0.0.0.0");
547       InfoServer infoServer = new InfoServer("thrift", a, port, false, conf);
548       infoServer.setAttribute("hbase.conf", conf);
549       infoServer.start();
550     }
551 
552     if (nonblocking) {
553       server = getTNonBlockingServer(protocolFactory,
554           processor,
555           transportFactory,
556           inetSocketAddress);
557     } else if (hsha) {
558       server = getTHsHaServer(protocolFactory,
559           processor,
560           transportFactory,
561           workerThreads,
562           maxCallQueueSize,
563           inetSocketAddress,
564           metrics);
565     } else if (selector) {
566       server = getTThreadedSelectorServer(protocolFactory,
567           processor,
568           transportFactory,
569           workerThreads,
570           selectorThreads,
571           maxCallQueueSize,
572           inetSocketAddress,
573           metrics);
574     } else {
575       server = getTThreadPoolServer(protocolFactory,
576           processor,
577           transportFactory,
578           workerThreads,
579           inetSocketAddress,
580           backlog,
581           readTimeout,
582           metrics);
583     }
584 
585     final TServer tserver = server;
586     realUser.doAs(
587       new PrivilegedAction<Object>() {
588         @Override
589         public Object run() {
590           tserver.serve();
591           return null;
592         }
593       });
594   }
595 }