add a ServerFactory class

This refactors the Server creation code, to make it easier to create new
Server implementations in the future, and to separate the LibEventServer
code from the main hphp_runtime library.

This defines a new ServerFactory interface, and a ServerFactoryRegistry
which maintains a mapping of server type strings to ServerFactory
objects.  The HttpServer code now uses a ServerFactory to create the
m_pageServer, rather than directly creating a LibEventServer object.
Esse commit está contido em:
Adam Simpkins
2013-05-29 12:06:49 -07:00
commit de Sara Golemon
commit be42cb5fdc
13 arquivos alterados com 218 adições e 53 exclusões
+2
Ver Arquivo
@@ -94,6 +94,7 @@ std::string RuntimeOption::AdminLogSymLink;
std::string RuntimeOption::Tier;
std::string RuntimeOption::Host;
std::string RuntimeOption::DefaultServerNameSuffix;
std::string RuntimeOption::ServerType = "libevent";
std::string RuntimeOption::ServerIP;
std::string RuntimeOption::ServerPrimaryIP;
int RuntimeOption::ServerPort;
@@ -670,6 +671,7 @@ void RuntimeOption::Load(Hdf &config, StringVec *overwrites /* = NULL */,
Hdf server = config["Server"];
Host = server["Host"].getString();
DefaultServerNameSuffix = server["DefaultServerNameSuffix"].getString();
ServerType = server["Type"].getString(ServerType);
ServerIP = server["IP"].getString();
ServerPrimaryIP = Util::GetPrimaryIP();
ServerPort = server["Port"].getUInt16(80);
+1
Ver Arquivo
@@ -89,6 +89,7 @@ public:
static std::string Tier;
static std::string Host;
static std::string DefaultServerNameSuffix;
static std::string ServerType;
static std::string ServerIP;
static std::string ServerPrimaryIP;
static int ServerPort;
@@ -17,8 +17,8 @@
#ifndef incl_HPHP_ADMIN_REQUEST_HANDLER_H_
#define incl_HPHP_ADMIN_REQUEST_HANDLER_H_
#include "hphp/runtime/base/server/libevent_server.h"
#include "hphp/runtime/base/server/access_log.h"
#include "hphp/runtime/base/server/server.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
+1 -1
Ver Arquivo
@@ -17,10 +17,10 @@
#ifndef incl_HPHP_HTTP_REQUEST_HANDLER_H_
#define incl_HPHP_HTTP_REQUEST_HANDLER_H_
#include "hphp/runtime/base/server/libevent_server.h"
#include "hphp/runtime/base/util/string_buffer.h"
#include "hphp/runtime/base/server/virtual_host.h"
#include "hphp/runtime/base/server/access_log.h"
#include "hphp/runtime/base/server/server.h"
namespace HPHP {
+16 -29
Ver Arquivo
@@ -15,9 +15,6 @@
*/
#include "hphp/runtime/base/server/http_server.h"
#include "hphp/runtime/base/server/libevent_server.h"
#include "hphp/runtime/base/server/libevent_server_with_fd.h"
#include "hphp/runtime/base/server/libevent_server_with_takeover.h"
#include "hphp/runtime/base/server/http_request_handler.h"
#include "hphp/runtime/base/server/admin_request_handler.h"
#include "hphp/runtime/base/server/server_stats.h"
@@ -34,6 +31,7 @@
#include "hphp/runtime/base/program_functions.h"
#include "hphp/runtime/debugger/debugger.h"
#include "hphp/util/db_conn.h"
#include "hphp/util/process.h"
#include "hphp/util/ssl_init.h"
#include "hphp/runtime/ext/ext_apc.h"
@@ -68,28 +66,16 @@ HttpServer::HttpServer(void *sslCTX /* = NULL */)
additionalThreads = RuntimeOption::ServerThreadCount - startingThreadCount;
}
if (RuntimeOption::ServerPortFd != -1 || RuntimeOption::SSLPortFd != -1) {
auto const server = boost::make_shared<LibEventServerWithFd>(
RuntimeOption::ServerIP, RuntimeOption::ServerPort,
startingThreadCount,
RuntimeOption::RequestTimeoutSeconds);
server->setServerSocketFd(RuntimeOption::ServerPortFd);
server->setSSLSocketFd(RuntimeOption::SSLPortFd);
m_pageServer = server;
} else if (RuntimeOption::TakeoverFilename.empty()) {
auto const server = boost::make_shared<LibEventServer>(
RuntimeOption::ServerIP, RuntimeOption::ServerPort,
startingThreadCount,
RuntimeOption::RequestTimeoutSeconds);
m_pageServer = server;
} else {
auto const server = boost::make_shared<LibEventServerWithTakeover>(
RuntimeOption::ServerIP, RuntimeOption::ServerPort,
startingThreadCount,
RuntimeOption::RequestTimeoutSeconds);
server->setTransferFilename(RuntimeOption::TakeoverFilename);
m_pageServer = server;
}
auto serverFactory = ServerFactoryRegistry::getInstance()->getFactory
(RuntimeOption::ServerType);
ServerOptions options
(RuntimeOption::ServerIP, RuntimeOption::ServerPort,
startingThreadCount,
std::chrono::seconds(RuntimeOption::RequestTimeoutSeconds));
options.m_serverFD = RuntimeOption::ServerPortFd;
options.m_sslFD = RuntimeOption::SSLPortFd;
options.m_takeoverFilename = RuntimeOption::TakeoverFilename;
m_pageServer = serverFactory->createServer(options);
m_pageServer->addTakeoverListener(this);
if (additionalThreads) {
@@ -108,10 +94,11 @@ HttpServer::HttpServer(void *sslCTX /* = NULL */)
m_pageServer->enableSSL(m_sslCTX, RuntimeOption::SSLPort);
}
m_adminServer = boost::make_shared<LibEventServer>(
RuntimeOption::ServerIP, RuntimeOption::AdminServerPort,
RuntimeOption::AdminThreadCount,
RuntimeOption::RequestTimeoutSeconds);
m_adminServer = ServerFactoryRegistry::createServer
(RuntimeOption::ServerType,
RuntimeOption::ServerIP, RuntimeOption::AdminServerPort,
RuntimeOption::AdminThreadCount,
std::chrono::seconds(RuntimeOption::RequestTimeoutSeconds));
m_adminServer->setRequestHandlerFactory<AdminRequestHandler>();
for (unsigned int i = 0; i < RuntimeOption::SatelliteServerInfos.size();
-1
Ver Arquivo
@@ -19,7 +19,6 @@
#include "hphp/runtime/base/server/server.h"
#include "hphp/runtime/base/server/satellite_server.h"
#include "hphp/runtime/base/server/libevent_server_with_takeover.h"
#include "hphp/util/async_func.h"
#include "hphp/runtime/base/server/service_thread.h"
@@ -0,0 +1,56 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "hphp/runtime/base/server/libevent_server.h"
#include "hphp/runtime/base/server/libevent_server_with_fd.h"
#include "hphp/runtime/base/server/libevent_server_with_takeover.h"
#include <boost/make_shared.hpp>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class LibEventServerFactory : public ServerFactory {
public:
LibEventServerFactory() {}
virtual ServerPtr createServer(const ServerOptions& options);
};
ServerPtr LibEventServerFactory::createServer(const ServerOptions& options) {
if (options.m_serverFD != -1 || options.m_sslFD != -1) {
auto const server = boost::make_shared<LibEventServerWithFd>
(options.m_address, options.m_port, options.m_numThreads,
options.m_timeout.count());
server->setServerSocketFd(options.m_serverFD);
server->setSSLSocketFd(options.m_sslFD);
return server;
}
if (!options.m_takeoverFilename.empty()) {
auto const server = boost::make_shared<LibEventServerWithTakeover>
(options.m_address, options.m_port, options.m_numThreads,
options.m_timeout.count());
server->setTransferFilename(options.m_takeoverFilename);
return server;
}
return boost::make_shared<LibEventServer>(options.m_address, options.m_port,
options.m_numThreads,
options.m_timeout.count());
}
///////////////////////////////////////////////////////////////////////////////
}
namespace {
/*
* Automatically register LibEventServerFactory on program start
*/
void register_libevent_server() __attribute__((constructor));
void register_libevent_server() {
auto registry = HPHP::ServerFactoryRegistry::getInstance();
auto factory = boost::make_shared<HPHP::LibEventServerFactory>();
registry->registerFactory("libevent", factory);
}
}
+14 -15
Ver Arquivo
@@ -15,7 +15,6 @@
*/
#include "hphp/runtime/base/server/satellite_server.h"
#include "hphp/runtime/base/server/libevent_server.h"
#include "hphp/runtime/base/server/http_request_handler.h"
#include "hphp/runtime/base/server/rpc_request_handler.h"
#include "hphp/runtime/base/server/virtual_host.h"
@@ -41,8 +40,8 @@ SatelliteServerInfo::SatelliteServerInfo(Hdf hdf) {
m_threadCount = hdf["ThreadCount"].getInt32(5);
m_maxRequest = hdf["MaxRequest"].getInt32(500);
m_maxDuration = hdf["MaxDuration"].getInt32(120);
m_timeoutSeconds =
hdf["TimeoutSeconds"].getInt32(RuntimeOption::RequestTimeoutSeconds);
m_timeoutSeconds = std::chrono::seconds
(hdf["TimeoutSeconds"].getInt32(RuntimeOption::RequestTimeoutSeconds));
m_reqInitFunc = hdf["RequestInitFunction"].getString("");
m_reqInitDoc = hdf["RequestInitDocument"].getString("");
m_password = hdf["Password"].getString("");
@@ -85,15 +84,15 @@ bool SatelliteServerInfo::checkMainURL(const std::string& path) {
}
///////////////////////////////////////////////////////////////////////////////
// InternalPageServer: LibEventServer + allowed URL checking
// InternalPageServer: Server + allowed URL checking
class InternalPageServer : public SatelliteServer {
public:
explicit InternalPageServer(SatelliteServerInfoPtr info)
: m_allowedURLs(info->getURLs()) {
m_server = boost::make_shared<LibEventServer>(
RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(),
info->getTimeoutSeconds());
m_server = ServerFactoryRegistry::createServer
(RuntimeOption::ServerType, RuntimeOption::ServerIP, info->getPort(),
info->getThreadCount(), info->getTimeoutSeconds());
m_server->setRequestHandlerFactory<HttpRequestHandler>();
m_server->setUrlChecker(std::bind(&InternalPageServer::checkURL, this,
std::placeholders::_1));
@@ -125,14 +124,14 @@ private:
};
///////////////////////////////////////////////////////////////////////////////
// DanglingPageServer: same as LibEventServer
// DanglingPageServer: same as Server
class DanglingPageServer : public SatelliteServer {
public:
explicit DanglingPageServer(SatelliteServerInfoPtr info) {
m_server = boost::make_shared<LibEventServer>(
RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(),
info->getTimeoutSeconds());
m_server = ServerFactoryRegistry::createServer
(RuntimeOption::ServerType, RuntimeOption::ServerIP, info->getPort(),
info->getThreadCount(), info->getTimeoutSeconds());
m_server->setRequestHandlerFactory<HttpRequestHandler>();
}
@@ -148,14 +147,14 @@ private:
};
///////////////////////////////////////////////////////////////////////////////
// RPCServer: LibEventServer + RPCRequestHandler
// RPCServer: Server + RPCRequestHandler
class RPCServer : public SatelliteServer {
public:
explicit RPCServer(SatelliteServerInfoPtr info) {
m_server = boost::make_shared<LibEventServer>(
RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(),
info->getTimeoutSeconds());
m_server = ServerFactoryRegistry::createServer
(RuntimeOption::ServerType, RuntimeOption::ServerIP, info->getPort(),
info->getThreadCount(), info->getTimeoutSeconds());
m_server->setRequestHandlerFactory([info] {
auto handler = make_unique<RPCRequestHandler>();
handler->setServerInfo(info);
+4 -2
Ver Arquivo
@@ -19,6 +19,8 @@
#include "hphp/util/hdf.h"
#include <chrono>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -76,7 +78,7 @@ public:
int getThreadCount() const { return m_threadCount;}
// for all libevent servers
int getTimeoutSeconds() const { return m_timeoutSeconds;}
std::chrono::seconds getTimeoutSeconds() const { return m_timeoutSeconds;}
// only for InternalPageServer
const std::set<std::string> &getURLs() const { return m_urls;}
@@ -97,7 +99,7 @@ protected:
int m_threadCount;
int m_maxRequest;
int m_maxDuration;
int m_timeoutSeconds;
std::chrono::seconds m_timeoutSeconds;
std::set<std::string> m_urls; // url regex patterns
std::string m_reqInitFunc;
std::string m_reqInitDoc;
+48
Ver Arquivo
@@ -54,5 +54,53 @@ Server::Server(const std::string &address, int port, int threadCount)
m_status(NOT_YET_STARTED) {
}
///////////////////////////////////////////////////////////////////////////////
ServerPtr ServerFactory::createServer(const std::string &address,
uint16_t port,
int numThreads,
std::chrono::seconds timeout) {
ServerOptions options(address, port, numThreads, timeout);
return createServer(options);
}
ServerFactoryRegistry::ServerFactoryRegistry()
: m_lock(false) {
}
ServerFactoryRegistry *ServerFactoryRegistry::getInstance() {
static ServerFactoryRegistry singleton;
return &singleton;
}
ServerPtr ServerFactoryRegistry::createServer(const std::string &type,
const std::string &address,
uint16_t port,
int numThreads,
std::chrono::seconds timeout) {
auto factory = getInstance()->getFactory(type);
ServerOptions options(address, port, numThreads, timeout);
return factory->createServer(options);
}
void ServerFactoryRegistry::registerFactory(const std::string &name,
const ServerFactoryPtr &factory) {
Lock lock(m_lock);
auto ret = m_factories.insert(std::make_pair(name, factory));
if (!ret.second) {
throw ServerException("a factory already exists for server type \"%s\"",
name.c_str());
}
}
ServerFactoryPtr ServerFactoryRegistry::getFactory(const std::string &name) {
Lock lock(m_lock);
auto it = m_factories.find(name);
if (it == m_factories.end()) {
throw ServerException("no factory for server type \"%s\"", name.c_str());
}
return it->second;
}
///////////////////////////////////////////////////////////////////////////////
}
+69
Ver Arquivo
@@ -21,6 +21,7 @@
#include "hphp/util/exception.h"
#include "hphp/util/lock.h"
#include <chrono>
#include <memory>
/**
@@ -67,6 +68,7 @@ namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Server);
DECLARE_BOOST_TYPES(ServerFactory);
/**
* Base class of an HTTP request handler. Defining minimal interface an
@@ -250,6 +252,73 @@ private:
RunStatus m_status;
};
class ServerOptions {
public:
ServerOptions(const std::string &address,
uint16_t port,
int numThreads,
std::chrono::seconds timeout)
: m_address(address),
m_port(port),
m_numThreads(numThreads),
m_timeout(timeout),
m_serverFD(-1),
m_sslFD(-1),
m_takeoverFilename() {
}
std::string m_address;
uint16_t m_port;
int m_numThreads;
std::chrono::seconds m_timeout;
int m_serverFD;
int m_sslFD;
std::string m_takeoverFilename;
};
/**
* A ServerFactory knows how to create Server objects.
*/
class ServerFactory : private boost::noncopyable {
public:
virtual ~ServerFactory() {}
virtual ServerPtr createServer(const ServerOptions &options) = 0;
ServerPtr createServer(const std::string &address,
uint16_t port,
int numThreads,
std::chrono::seconds timeout);
};
/**
* A registry mapping server type names to ServerFactory objects.
*
* This allows new server types to be plugged in dynamically, without having to
* hard code the list of all possible server types.
*/
class ServerFactoryRegistry : private boost::noncopyable {
public:
ServerFactoryRegistry();
static ServerFactoryRegistry *getInstance();
static ServerPtr createServer(const std::string &type,
const std::string &address,
uint16_t port,
int numThreads,
std::chrono::seconds timeout);
void registerFactory(const std::string &name,
const ServerFactoryPtr &factory);
ServerFactoryPtr getFactory(const std::string &name);
private:
Mutex m_lock;
std::map<std::string, ServerFactoryPtr> m_factories;
};
/**
* All exceptions Server throws should derive from this base class.
*/
+5 -4
Ver Arquivo
@@ -25,6 +25,7 @@
#include "hphp/runtime/base/array/array_init.h"
#include "hphp/util/json.h"
#include "hphp/util/compatibility.h"
#include "hphp/util/process.h"
#include "hphp/runtime/base/hardware_counter.h"
using std::list;
@@ -307,7 +308,7 @@ void ServerStats::FreeSlots(list<TimeSlot*> &slots) {
class Writer {
public:
Writer(ostream &out) : m_out(out), m_indent(0) {}
explicit Writer(ostream &out) : m_out(out), m_indent(0) {}
virtual ~Writer() {}
virtual void writeFileHeader() = 0;
@@ -350,7 +351,7 @@ protected:
class XMLWriter : public Writer {
public:
XMLWriter(ostream &out) : Writer(out) {}
explicit XMLWriter(ostream &out) : Writer(out) {}
virtual void writeFileHeader() {
@@ -484,7 +485,7 @@ protected:
public:
JSONWriter(ostream &out) : Writer(out),
explicit JSONWriter(ostream &out) : Writer(out),
m_justIndented(true) {
// A valid json object begins in the nameless context. See
@@ -535,7 +536,7 @@ public:
class HTMLWriter : public Writer {
public:
HTMLWriter(ostream &out) : Writer(out) {}
explicit HTMLWriter(ostream &out) : Writer(out) {}
virtual void writeFileHeader() {
m_out << "<!doctype html>\n<html>\n<head>\n"
+1
Ver Arquivo
@@ -28,6 +28,7 @@
#include "hphp/runtime/base/server/http_request_handler.h"
#include "hphp/runtime/base/util/http_client.h"
#include "hphp/runtime/base/runtime_option.h"
#include "hphp/runtime/base/server/libevent_server.h"
#include <boost/make_shared.hpp>