forked from mindspore-Ecosystem/mindspore
Added http server based on libevent
This commit is contained in:
parent
fa37f8fde3
commit
28c9e9d9a5
|
@ -73,6 +73,16 @@ if (USE_GLOG)
|
|||
)
|
||||
endif ()
|
||||
|
||||
file(GLOB_RECURSE LIBEVENT_LIB_LIST
|
||||
${libevent_LIBPATH}/libevent*
|
||||
${libevent_LIBPATH}/libevent_pthreads*
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${LIBEVENT_LIB_LIST}
|
||||
DESTINATION ${INSTALL_LIB_DIR}
|
||||
COMPONENT mindspore
|
||||
)
|
||||
if (ENABLE_MINDDATA)
|
||||
install(
|
||||
TARGETS _c_dataengine _c_mindrecord
|
||||
|
|
|
@ -278,7 +278,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
|||
target_link_libraries(_c_expression PRIVATE -Wl,--whole-archive mindspore -Wl,--no-whole-archive)
|
||||
else ()
|
||||
if (ENABLE_CPU AND (ENABLE_D OR ENABLE_GPU))
|
||||
target_link_libraries(mindspore mindspore::pslite mindspore::protobuf ${zeromq_DIRPATH}/zmq_install/lib/libzmq.a)
|
||||
target_link_libraries(mindspore mindspore::pslite mindspore::protobuf mindspore::event mindspore::event_pthreads ${zeromq_DIRPATH}/zmq_install/lib/libzmq.a)
|
||||
if (${ENABLE_IBVERBS} STREQUAL "ON")
|
||||
target_link_libraries(mindspore ibverbs rdmacm)
|
||||
endif()
|
||||
|
|
|
@ -5,6 +5,8 @@ if (NOT (ENABLE_CPU AND (ENABLE_D OR ENABLE_GPU)))
|
|||
list(REMOVE_ITEM _PS_SRC_FILES "optimizer_info.cc")
|
||||
list(REMOVE_ITEM _PS_SRC_FILES "scheduler.cc")
|
||||
list(REMOVE_ITEM _PS_SRC_FILES "util.cc")
|
||||
list(REMOVE_ITEM _PS_SRC_FILES "comm/http_message_handler.cc")
|
||||
list(REMOVE_ITEM _PS_SRC_FILES "comm/http_server.cc")
|
||||
endif()
|
||||
|
||||
set_property(SOURCE ${_PS_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_PS)
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ps/comm/http_message_handler.h"
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/bufferevent_compat.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/http_compat.h>
|
||||
#include <event2/http_struct.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace mindspore {
|
||||
namespace ps {
|
||||
namespace comm {
|
||||
|
||||
HttpMessageHandler::~HttpMessageHandler() {
|
||||
if (!event_request_) {
|
||||
evhttp_request_free(event_request_);
|
||||
event_request_ = nullptr;
|
||||
}
|
||||
if (!event_uri_) {
|
||||
evhttp_uri_free(const_cast<evhttp_uri *>(event_uri_));
|
||||
event_uri_ = nullptr;
|
||||
}
|
||||
if (!resp_buf_) {
|
||||
evbuffer_free(resp_buf_);
|
||||
resp_buf_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HttpMessageHandler::InitHttpMessage() {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
event_uri_ = evhttp_request_get_evhttp_uri(event_request_);
|
||||
MS_EXCEPTION_IF_NULL(event_uri_);
|
||||
|
||||
const char *query = evhttp_uri_get_query(event_uri_);
|
||||
if (query) {
|
||||
evhttp_parse_query_str(query, &path_params_);
|
||||
}
|
||||
|
||||
head_params_ = evhttp_request_get_input_headers(event_request_);
|
||||
resp_headers_ = evhttp_request_get_output_headers(event_request_);
|
||||
resp_buf_ = evhttp_request_get_output_buffer(event_request_);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetHeadParam(const std::string &key) {
|
||||
MS_EXCEPTION_IF_NULL(head_params_);
|
||||
const char *val = evhttp_find_header(head_params_, key.c_str());
|
||||
MS_EXCEPTION_IF_NULL(val);
|
||||
return std::string(val);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetPathParam(const std::string &key) {
|
||||
const char *val = evhttp_find_header(&path_params_, key.c_str());
|
||||
MS_EXCEPTION_IF_NULL(val);
|
||||
return std::string(val);
|
||||
}
|
||||
|
||||
void HttpMessageHandler::ParsePostParam() {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
size_t len = evbuffer_get_length(event_request_->input_buffer);
|
||||
if (len == 0) {
|
||||
MS_LOG(EXCEPTION) << "The post parameter size is: " << len;
|
||||
}
|
||||
post_param_parsed_ = true;
|
||||
const char *post_message = reinterpret_cast<const char *>(evbuffer_pullup(event_request_->input_buffer, -1));
|
||||
MS_EXCEPTION_IF_NULL(post_message);
|
||||
body_ = std::make_unique<std::string>(post_message, len);
|
||||
int ret = evhttp_parse_query_str(body_->c_str(), &post_params_);
|
||||
if (ret == -1) {
|
||||
MS_LOG(EXCEPTION) << "Parse post parameter failed!";
|
||||
}
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetPostParam(const std::string &key) {
|
||||
if (!post_param_parsed_) {
|
||||
ParsePostParam();
|
||||
}
|
||||
|
||||
const char *val = evhttp_find_header(&post_params_, key.c_str());
|
||||
MS_EXCEPTION_IF_NULL(val);
|
||||
return std::string(val);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetRequestUri() {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
const char *uri = evhttp_request_get_uri(event_request_);
|
||||
MS_EXCEPTION_IF_NULL(uri);
|
||||
return std::string(uri);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetRequestHost() {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
const char *host = evhttp_request_get_host(event_request_);
|
||||
MS_EXCEPTION_IF_NULL(host);
|
||||
return std::string(host);
|
||||
}
|
||||
|
||||
int HttpMessageHandler::GetUriPort() {
|
||||
MS_EXCEPTION_IF_NULL(event_uri_);
|
||||
return evhttp_uri_get_port(event_uri_);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetUriPath() {
|
||||
MS_EXCEPTION_IF_NULL(event_uri_);
|
||||
const char *path = evhttp_uri_get_path(event_uri_);
|
||||
MS_EXCEPTION_IF_NULL(path);
|
||||
return std::string(path);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetUriQuery() {
|
||||
MS_EXCEPTION_IF_NULL(event_uri_);
|
||||
const char *query = evhttp_uri_get_query(event_uri_);
|
||||
MS_EXCEPTION_IF_NULL(query);
|
||||
return std::string(query);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetUriFragment() {
|
||||
MS_EXCEPTION_IF_NULL(event_uri_);
|
||||
const char *fragment = evhttp_uri_get_fragment(event_uri_);
|
||||
MS_EXCEPTION_IF_NULL(fragment);
|
||||
return std::string(fragment);
|
||||
}
|
||||
|
||||
std::string HttpMessageHandler::GetPostMsg() {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
if (body_ != nullptr) {
|
||||
return *body_;
|
||||
}
|
||||
size_t len = evbuffer_get_length(event_request_->input_buffer);
|
||||
if (len == 0) {
|
||||
MS_LOG(EXCEPTION) << "The post message is empty!";
|
||||
}
|
||||
const char *post_message = reinterpret_cast<const char *>(evbuffer_pullup(event_request_->input_buffer, -1));
|
||||
MS_EXCEPTION_IF_NULL(post_message);
|
||||
body_ = std::make_unique<std::string>(post_message, len);
|
||||
return *body_;
|
||||
}
|
||||
|
||||
void HttpMessageHandler::AddRespHeadParam(const std::string &key, const std::string &val) {
|
||||
MS_EXCEPTION_IF_NULL(resp_headers_);
|
||||
if (evhttp_add_header(resp_headers_, key.c_str(), val.c_str()) != 0) {
|
||||
MS_LOG(EXCEPTION) << "Add parameter of response header failed.";
|
||||
}
|
||||
}
|
||||
|
||||
void HttpMessageHandler::AddRespHeaders(const HttpHeaders &headers) {
|
||||
for (auto iter = headers.begin(); iter != headers.end(); ++iter) {
|
||||
auto list = iter->second;
|
||||
for (auto iterator_val = list.begin(); iterator_val != list.end(); ++iterator_val) {
|
||||
AddRespHeadParam(iter->first, *iterator_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HttpMessageHandler::AddRespString(const std::string &str) {
|
||||
MS_EXCEPTION_IF_NULL(resp_buf_);
|
||||
if (evbuffer_add_printf(resp_buf_, "%s", str.c_str()) == -1) {
|
||||
MS_LOG(EXCEPTION) << "Add string to response body failed.";
|
||||
}
|
||||
}
|
||||
|
||||
void HttpMessageHandler::SetRespCode(int code) { resp_code_ = code; }
|
||||
|
||||
void HttpMessageHandler::SendResponse() {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
MS_EXCEPTION_IF_NULL(resp_buf_);
|
||||
evhttp_send_reply(event_request_, resp_code_, nullptr, resp_buf_);
|
||||
}
|
||||
|
||||
void HttpMessageHandler::QuickResponse(int code, const std::string &body) {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
MS_EXCEPTION_IF_NULL(resp_buf_);
|
||||
AddRespString(body);
|
||||
evhttp_send_reply(event_request_, code, nullptr, resp_buf_);
|
||||
}
|
||||
|
||||
void HttpMessageHandler::SimpleResponse(int code, const HttpHeaders &headers, const std::string &body) {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
MS_EXCEPTION_IF_NULL(resp_buf_);
|
||||
AddRespHeaders(headers);
|
||||
AddRespString(body);
|
||||
MS_EXCEPTION_IF_NULL(resp_buf_);
|
||||
evhttp_send_reply(event_request_, resp_code_, nullptr, resp_buf_);
|
||||
}
|
||||
|
||||
void HttpMessageHandler::RespError(int nCode, const std::string &message) {
|
||||
MS_EXCEPTION_IF_NULL(event_request_);
|
||||
if (message.empty()) {
|
||||
evhttp_send_error(event_request_, nCode, nullptr);
|
||||
} else {
|
||||
evhttp_send_error(event_request_, nCode, message.c_str());
|
||||
}
|
||||
}
|
||||
} // namespace comm
|
||||
} // namespace ps
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MINDSPORE_CCSRC_PS_COMM_HTTP_MESSAGE_HANDLER_H_
|
||||
#define MINDSPORE_CCSRC_PS_COMM_HTTP_MESSAGE_HANDLER_H_
|
||||
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/keyvalq_struct.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include "utils/log_adapter.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace ps {
|
||||
namespace comm {
|
||||
|
||||
typedef std::map<std::string, std::list<std::string>> HttpHeaders;
|
||||
|
||||
class HttpMessageHandler {
|
||||
public:
|
||||
explicit HttpMessageHandler(struct evhttp_request *req)
|
||||
: event_request_(req),
|
||||
event_uri_(nullptr),
|
||||
path_params_{0},
|
||||
head_params_(nullptr),
|
||||
post_params_{0},
|
||||
post_param_parsed_(false),
|
||||
body_(nullptr),
|
||||
resp_headers_(nullptr),
|
||||
resp_buf_(nullptr),
|
||||
resp_code_(HTTP_OK) {}
|
||||
|
||||
~HttpMessageHandler();
|
||||
|
||||
void InitHttpMessage();
|
||||
std::string GetRequestUri();
|
||||
std::string GetRequestHost();
|
||||
std::string GetHeadParam(const std::string &key);
|
||||
std::string GetPathParam(const std::string &key);
|
||||
std::string GetPostParam(const std::string &key);
|
||||
std::string GetPostMsg();
|
||||
std::string GetUriPath();
|
||||
std::string GetUriQuery();
|
||||
|
||||
// It will return -1 if no port set
|
||||
int GetUriPort();
|
||||
|
||||
// Useless to get from a request url, fragment is only for browser to locate sth.
|
||||
std::string GetUriFragment();
|
||||
|
||||
void AddRespHeadParam(const std::string &key, const std::string &val);
|
||||
void AddRespHeaders(const HttpHeaders &headers);
|
||||
void AddRespString(const std::string &str);
|
||||
void SetRespCode(int code);
|
||||
|
||||
// Make sure code and all response body has finished set
|
||||
void SendResponse();
|
||||
void QuickResponse(int code, const std::string &body);
|
||||
void SimpleResponse(int code, const HttpHeaders &headers, const std::string &body);
|
||||
|
||||
// If message is empty, libevent will use default error code message instead
|
||||
void RespError(int nCode, const std::string &message);
|
||||
|
||||
private:
|
||||
struct evhttp_request *event_request_;
|
||||
const struct evhttp_uri *event_uri_;
|
||||
struct evkeyvalq path_params_;
|
||||
struct evkeyvalq *head_params_;
|
||||
struct evkeyvalq post_params_;
|
||||
bool post_param_parsed_;
|
||||
std::unique_ptr<std::string> body_;
|
||||
struct evkeyvalq *resp_headers_;
|
||||
struct evbuffer *resp_buf_;
|
||||
int resp_code_;
|
||||
|
||||
// Body length should no more than MAX_POST_BODY_LEN, default 64kB
|
||||
void ParsePostParam();
|
||||
};
|
||||
|
||||
} // namespace comm
|
||||
} // namespace ps
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_PS_COMM_HTTP_MESSAGE_HANDLER_H_
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ps/comm/http_server.h"
|
||||
#include "ps/comm/http_message_handler.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <WinSock2.h>
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#include <event.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/bufferevent_compat.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/http_compat.h>
|
||||
#include <event2/http_struct.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
|
||||
namespace mindspore {
|
||||
namespace ps {
|
||||
namespace comm {
|
||||
|
||||
HttpServer::~HttpServer() {
|
||||
if (event_http_) {
|
||||
evhttp_free(event_http_);
|
||||
event_http_ = nullptr;
|
||||
}
|
||||
if (event_base_) {
|
||||
event_base_free(event_base_);
|
||||
event_base_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpServer::InitServer() {
|
||||
if (!CheckIp(server_address_)) {
|
||||
MS_LOG(EXCEPTION) << "Server address" << server_address_ << " illegal!";
|
||||
}
|
||||
int64_t uAddr = inet_addr(server_address_.c_str());
|
||||
if (INADDR_NONE == uAddr) {
|
||||
MS_LOG(EXCEPTION) << "Server address illegal, inet_addr converting failed!";
|
||||
}
|
||||
if (server_port_ <= 0) {
|
||||
MS_LOG(EXCEPTION) << "Server port:" << server_port_ << " illegal!";
|
||||
}
|
||||
|
||||
event_base_ = event_base_new();
|
||||
MS_EXCEPTION_IF_NULL(event_base_);
|
||||
event_http_ = evhttp_new(event_base_);
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
int ret = evhttp_bind_socket(event_http_, server_address_.c_str(), server_port_);
|
||||
if (ret != 0) {
|
||||
MS_LOG(EXCEPTION) << "Http bind server addr:" << server_address_.c_str() << " port:" << server_port_ << "failed";
|
||||
}
|
||||
is_init_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HttpServer::CheckIp(const std::string &ip) {
|
||||
std::regex pattern("((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)");
|
||||
std::smatch res;
|
||||
if (regex_match(ip, res, pattern)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HttpServer::SetTimeOut(int seconds) {
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
if (seconds < 0) {
|
||||
MS_LOG(EXCEPTION) << "The timeout seconds:" << seconds << "is less than 0!";
|
||||
}
|
||||
evhttp_set_timeout(event_http_, seconds);
|
||||
}
|
||||
|
||||
void HttpServer::SetAllowedMethod(HttpMethodsSet methods) {
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
evhttp_set_allowed_methods(event_http_, methods);
|
||||
}
|
||||
|
||||
void HttpServer::SetMaxHeaderSize(size_t num) {
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
if (num < 0) {
|
||||
MS_LOG(EXCEPTION) << "The header num:" << num << "is less than 0!";
|
||||
}
|
||||
evhttp_set_max_headers_size(event_http_, num);
|
||||
}
|
||||
|
||||
void HttpServer::SetMaxBodySize(size_t num) {
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
if (num < 0) {
|
||||
MS_LOG(EXCEPTION) << "The max body num:" << num << "is less than 0!";
|
||||
}
|
||||
evhttp_set_max_body_size(event_http_, num);
|
||||
}
|
||||
|
||||
bool HttpServer::RegisterRoute(const std::string &url, handle_t *function) {
|
||||
if ((!is_init_) && (!InitServer())) {
|
||||
MS_LOG(EXCEPTION) << "Init http server failed!";
|
||||
}
|
||||
HandlerFunc func = function;
|
||||
if (!func) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto TransFunc = [](struct evhttp_request *req, void *arg) {
|
||||
MS_EXCEPTION_IF_NULL(req);
|
||||
MS_EXCEPTION_IF_NULL(arg);
|
||||
HttpMessageHandler httpReq(req);
|
||||
httpReq.InitHttpMessage();
|
||||
handle_t *f = reinterpret_cast<handle_t *>(arg);
|
||||
f(&httpReq);
|
||||
};
|
||||
handle_t **pph = func.target<handle_t *>();
|
||||
MS_EXCEPTION_IF_NULL(pph);
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
|
||||
// O SUCCESS,-1 ALREADY_EXIST,-2 FAILURE
|
||||
int ret = evhttp_set_cb(event_http_, url.c_str(), TransFunc, reinterpret_cast<void *>(*pph));
|
||||
if (ret == 0) {
|
||||
MS_LOG(INFO) << "Ev http register handle of:" << url.c_str() << " success.";
|
||||
} else if (ret == -1) {
|
||||
MS_LOG(WARNING) << "Ev http register handle of:" << url.c_str() << " exist.";
|
||||
} else {
|
||||
MS_LOG(ERROR) << "Ev http register handle of:" << url.c_str() << " failed.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HttpServer::UnRegisterRoute(const std::string &url) {
|
||||
MS_EXCEPTION_IF_NULL(event_http_);
|
||||
return (evhttp_del_cb(event_http_, url.c_str()) == 0);
|
||||
}
|
||||
|
||||
bool HttpServer::Start() {
|
||||
MS_EXCEPTION_IF_NULL(event_base_);
|
||||
int ret = event_base_dispatch(event_base_);
|
||||
if (ret == 0) {
|
||||
MS_LOG(INFO) << "Event base dispatch success!";
|
||||
return true;
|
||||
} else if (ret == 1) {
|
||||
MS_LOG(ERROR) << "Event base dispatch failed with no events pending or active!";
|
||||
return false;
|
||||
} else if (ret == -1) {
|
||||
MS_LOG(ERROR) << "Event base dispatch failed with error occurred!";
|
||||
return false;
|
||||
} else {
|
||||
MS_LOG(EXCEPTION) << "Event base dispatch with unexpect error code!";
|
||||
}
|
||||
}
|
||||
|
||||
void HttpServer::Stop() {
|
||||
if (event_http_) {
|
||||
evhttp_free(event_http_);
|
||||
event_http_ = nullptr;
|
||||
}
|
||||
if (event_base_) {
|
||||
event_base_free(event_base_);
|
||||
event_base_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace comm
|
||||
} // namespace ps
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MINDSPORE_CCSRC_PS_COMM_HTTP_SERVER_H_
|
||||
#define MINDSPORE_CCSRC_PS_COMM_HTTP_SERVER_H_
|
||||
|
||||
#include "ps/comm/http_message_handler.h"
|
||||
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/keyvalq_struct.h>
|
||||
#include <event2/listener.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace mindspore {
|
||||
namespace ps {
|
||||
namespace comm {
|
||||
|
||||
typedef enum eHttpMethod {
|
||||
HM_GET = 1 << 0,
|
||||
HM_POST = 1 << 1,
|
||||
HM_HEAD = 1 << 2,
|
||||
HM_PUT = 1 << 3,
|
||||
HM_DELETE = 1 << 4,
|
||||
HM_OPTIONS = 1 << 5,
|
||||
HM_TRACE = 1 << 6,
|
||||
HM_CONNECT = 1 << 7,
|
||||
HM_PATCH = 1 << 8
|
||||
} HttpMethod;
|
||||
|
||||
typedef u_int16_t HttpMethodsSet;
|
||||
|
||||
typedef void(handle_t)(HttpMessageHandler *);
|
||||
|
||||
class HttpServer {
|
||||
public:
|
||||
// Server address only support IPV4 now, and should be in format of "x.x.x.x"
|
||||
explicit HttpServer(const std::string &address, std::int16_t port)
|
||||
: server_address_(address), server_port_(port), event_base_(nullptr), event_http_(nullptr), is_init_(false) {}
|
||||
|
||||
~HttpServer();
|
||||
|
||||
typedef std::function<handle_t> HandlerFunc;
|
||||
|
||||
bool InitServer();
|
||||
static bool CheckIp(const std::string &ip);
|
||||
void SetTimeOut(int seconds = 5);
|
||||
|
||||
// Default allowed methods: GET, POST, HEAD, PUT, DELETE
|
||||
void SetAllowedMethod(HttpMethodsSet methods);
|
||||
|
||||
// Default to ((((unsigned long long)0xffffffffUL) << 32) | 0xffffffffUL)
|
||||
void SetMaxHeaderSize(std::size_t num);
|
||||
|
||||
// Default to ((((unsigned long long)0xffffffffUL) << 32) | 0xffffffffUL)
|
||||
void SetMaxBodySize(std::size_t num);
|
||||
|
||||
// Return: true if success, false if failed, check log to find failure reason
|
||||
bool RegisterRoute(const std::string &url, handle_t *func);
|
||||
bool UnRegisterRoute(const std::string &url);
|
||||
|
||||
bool Start();
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
std::string server_address_;
|
||||
std::int16_t server_port_;
|
||||
struct event_base *event_base_;
|
||||
struct evhttp *event_http_;
|
||||
bool is_init_;
|
||||
};
|
||||
|
||||
} // namespace comm
|
||||
} // namespace ps
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // MINDSPORE_CCSRC_PS_COMM_HTTP_SERVER_H_
|
|
@ -55,6 +55,7 @@ if(ENABLE_MINDDATA)
|
|||
./transform/*.cc
|
||||
./utils/*.cc
|
||||
./vm/*.cc
|
||||
./ps/*.cc
|
||||
)
|
||||
|
||||
if(NOT ENABLE_PYTHON)
|
||||
|
@ -128,6 +129,7 @@ file(GLOB_RECURSE MINDSPORE_SRC_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
|||
"../../../mindspore/ccsrc/backend/session/kernel_build_client.cc"
|
||||
"../../../mindspore/ccsrc/transform/graph_ir/*.cc"
|
||||
"../../../mindspore/ccsrc/transform/graph_ir/op_declare/*.cc"
|
||||
"../../../mindspore/ccsrc/ps/*.cc"
|
||||
)
|
||||
|
||||
list(REMOVE_ITEM MINDSPORE_SRC_LIST "../../../mindspore/ccsrc/frontend/parallel/strategy_checkpoint/parallel_strategy_checkpoint.cc")
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ps/comm/http_server.h"
|
||||
#include "common/common_test.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace mindspore {
|
||||
namespace ps {
|
||||
namespace comm {
|
||||
|
||||
class TestHttpServer : public UT::Common {
|
||||
public:
|
||||
TestHttpServer() {}
|
||||
|
||||
static void testGetHandler(HttpMessageHandler *resp) {
|
||||
std::string host = resp->GetRequestHost();
|
||||
EXPECT_STREQ(host.c_str(), "127.0.0.1");
|
||||
|
||||
std::string path_param = resp->GetPathParam("key1");
|
||||
std::string header_param = resp->GetHeadParam("headerKey");
|
||||
std::string post_param = resp->GetPostParam("postKey");
|
||||
std::string post_message = resp->GetPostMsg();
|
||||
EXPECT_STREQ(path_param.c_str(), "value1");
|
||||
EXPECT_STREQ(header_param.c_str(), "headerValue");
|
||||
EXPECT_STREQ(post_param.c_str(), "postValue");
|
||||
EXPECT_STREQ(post_message.c_str(), "postKey=postValue");
|
||||
|
||||
const std::string rKey("headKey");
|
||||
const std::string rVal("headValue");
|
||||
const std::string rBody("post request success!\n");
|
||||
resp->AddRespHeadParam(rKey, rVal);
|
||||
resp->AddRespString(rBody);
|
||||
|
||||
resp->SetRespCode(200);
|
||||
resp->SendResponse();
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
server_ = new HttpServer("0.0.0.0", 9999);
|
||||
server_->RegisterRoute("/httpget", [](HttpMessageHandler *resp) {
|
||||
EXPECT_STREQ(resp->GetPathParam("key1").c_str(), "value1");
|
||||
EXPECT_STREQ(resp->GetUriQuery().c_str(), "key1=value1");
|
||||
EXPECT_STREQ(resp->GetRequestUri().c_str(), "/httpget?key1=value1");
|
||||
EXPECT_STREQ(resp->GetUriPath().c_str(), "/httpget");
|
||||
resp->QuickResponse(200, "get request success!\n");
|
||||
});
|
||||
server_->RegisterRoute("/handler", TestHttpServer::testGetHandler);
|
||||
std::unique_ptr<std::thread> http_server_thread_(nullptr);
|
||||
http_server_thread_.reset(new std::thread([&]() { server_->Start(); }));
|
||||
http_server_thread_->detach();
|
||||
}
|
||||
|
||||
void TearDown() override { server_->Stop(); }
|
||||
|
||||
private:
|
||||
HttpServer *server_;
|
||||
};
|
||||
|
||||
TEST_F(TestHttpServer, httpGetQequest) {
|
||||
char buffer[100];
|
||||
FILE *file;
|
||||
std::string cmd = "curl -X GET http://127.0.0.1:9999/httpget?key1=value1";
|
||||
std::string result;
|
||||
const char *sysCommand = cmd.data();
|
||||
if ((file = popen(sysCommand, "r")) == nullptr) {
|
||||
return;
|
||||
}
|
||||
while (fgets(buffer, sizeof(buffer) - 1, file) != nullptr) {
|
||||
result += buffer;
|
||||
}
|
||||
EXPECT_STREQ("get request success!\n", result.c_str());
|
||||
pclose(file);
|
||||
}
|
||||
|
||||
TEST_F(TestHttpServer, messageHandler) {
|
||||
char buffer[100];
|
||||
FILE *file;
|
||||
std::string cmd =
|
||||
R"(curl -X POST -d 'postKey=postValue' -i -H "Accept: application/json" -H "headerKey: headerValue" http://127.0.0.1:9999/handler?key1=value1)";
|
||||
std::string result;
|
||||
const char *sysCommand = cmd.data();
|
||||
if ((file = popen(sysCommand, "r")) == nullptr) {
|
||||
return;
|
||||
}
|
||||
while (fgets(buffer, sizeof(buffer) - 1, file) != nullptr) {
|
||||
result += buffer;
|
||||
}
|
||||
EXPECT_STREQ("post request success!\n", result.substr(result.find("post")).c_str());
|
||||
pclose(file);
|
||||
}
|
||||
|
||||
TEST_F(TestHttpServer, portException) {
|
||||
HttpServer *server_exception = new HttpServer("0.0.0.0", -1);
|
||||
ASSERT_THROW(server_exception->RegisterRoute("/handler", TestHttpServer::testGetHandler), std::exception);
|
||||
}
|
||||
|
||||
TEST_F(TestHttpServer, addressException) {
|
||||
HttpServer *server_exception = new HttpServer("12344.0.0.0", 9998);
|
||||
ASSERT_THROW(server_exception->RegisterRoute("/handler", TestHttpServer::testGetHandler), std::exception);
|
||||
}
|
||||
|
||||
} // namespace comm
|
||||
} // namespace ps
|
||||
} // namespace mindspore
|
Loading…
Reference in New Issue