facebook presto源码解读(part1)
——————原创文章,如有转载请说明出处
边学变卖,把代码查看结果汇报给各位读者,如有不对请指正。
part1主要是介绍整体的代码结构和大致的运行流程。
代码是在2016年8月从官网下载的。整体结构如下:
presto 客户端代码在presto-cli模块
但presto服务端代码不在presto-server,打开presto-server模块可以发现他采用maven的插件进行编译打包,改模块只有该规则文件。
presto服务端代码在presto-main模块。PrestoServer类启动服务器。
其他模块简述:
presto-base-jdbc 关系型数据库连接器的公共模块
presto-mysql mysql连接器用到了presto-base-jdbc
presto-jdbc jdbc客户端/另一种是cli
presto-hive-* hive连接器相关代码
presto-orc hive连接器读取hdfs的orc文件,并做了一些优化
presto-ml machine learning,未实现,打算ing
presto-kafka/cassadra/jmx 各种连接器
下面介绍客户端连接服务器进行sql语句的运行。主要运行ddl语句和Select语句,还有insert语句。
client入口代码在Presto类
package com.facebook.presto.cli;
import static io.airlift.airline.SingleCommand.singleCommand;
public final class Presto
{
private Presto() {}
public static void main(String[] args)
throws Exception
{
Console console = singleCommand(Console.class).parse(args);
if (console.helpOption.showHelpIfRequested() ||
console.versionOption.showVersionIfRequested()) {
return;
}
console.run();
}
}
进入Console类的run方法,
public void run()
{
ClientSession session = clientOptions.toClientSession();
KerberosConfig kerberosConfig = clientOptions.toKerberosConfig();
boolean hasQuery = !Strings.isNullOrEmpty(clientOptions.execute);
boolean isFromFile = !Strings.isNullOrEmpty(clientOptions.file);
if (!hasQuery || !isFromFile) {
AnsiConsole.systemInstall();
}
initializeLogging(clientOptions.logLevelsFile);
String query = clientOptions.execute;
if (hasQuery) {
query += ";";
}
if (isFromFile) {
if (hasQuery) {
throw new RuntimeException("both --execute and --file specified");
}
try {
query = Files.toString(new File(clientOptions.file), UTF_8);
hasQuery = true;
}
catch (IOException e) {
throw new RuntimeException(format("Error reading from file %s: %s", clientOptions.file, e.getMessage()));
}
}
try (QueryRunner queryRunner = QueryRunner.create(
session,
Optional.ofNullable(clientOptions.socksProxy),
Optional.ofNullable(clientOptions.keystorePath),
Optional.ofNullable(clientOptions.keystorePassword),
Optional.ofNullable(clientOptions.krb5Principal),
Optional.ofNullable(clientOptions.krb5RemoteServiceName),
clientOptions.authenticationEnabled,
kerberosConfig)) {
if (hasQuery) {
executeCommand(queryRunner, query, clientOptions.outputFormat);
}
else {
runConsole(queryRunner, session);
}
}
}
进入 executeCommand(queryRunner, query, clientOptions.outputFormat);方法:
private static void executeCommand(QueryRunner queryRunner, String query, OutputFormat outputFormat)
{
StatementSplitter splitter = new StatementSplitter(query);
for (Statement split : splitter.getCompleteStatements()) {
if (!isEmptyStatement(split.statement())) {
process(queryRunner, split.statement(), outputFormat, false);
}
}
if (!isEmptyStatement(splitter.getPartialStatement())) {
System.err.println("Non-terminated statement: " + splitter.getPartialStatement());
}
}
进入process方法,
private static void process(QueryRunner queryRunner, String sql, OutputFormat outputFormat, boolean interactive)
{
try (Query query = queryRunner.startQuery(sql)) {
query.renderOutput(System.out, outputFormat, interactive);
ClientSession session = queryRunner.getSession();
// update session properties if present
if (!query.getSetSessionProperties().isEmpty() || !query.getResetSessionProperties().isEmpty()) {
Map<String, String> sessionProperties = new HashMap<>(session.getProperties());
sessionProperties.putAll(query.getSetSessionProperties());
sessionProperties.keySet().removeAll(query.getResetSessionProperties());
session = withProperties(session, sessionProperties);
}
// update transaction ID if necessary
if (query.isClearTransactionId()) {
session = stripTransactionId(session);
}
if (query.getStartedTransactionId() != null) {
session = withTransactionId(session, query.getStartedTransactionId());
}
queryRunner.setSession(session);
}
catch (RuntimeException e) {
System.err.println("Error running command: " + e.getMessage());
if (queryRunner.getSession().isDebug()) {
e.printStackTrace();
}
}
}
进入Query query = queryRunner.startQuery(sql)方法发送rest请求到server端进行运行:
public Query startQuery(String query)
{
return new Query(startInternalQuery(query));
}
public StatementClient startInternalQuery(String query)
{
return new StatementClient(httpClient, queryResultsCodec, session.