1/**
2 * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15
16 * \author Haichao.chc
17 * \date Oct 2020
18 * \brief Implementation of http server
19 */
20
21#include "http_server.h"
22#include <chrono>
23#include "common/config.h"
24#include "common/error_code.h"
25#include "common/logger.h"
26
27extern std::string GetVersion();
28
29namespace proxima {
30namespace be {
31namespace server {
32
33
34HttpServerUPtr HttpServer::Create() {
35 return std::unique_ptr<HttpServer>(new HttpServer());
36}
37
38HttpServer::~HttpServer() {
39 if (thread_ != nullptr) {
40 this->stop();
41 }
42}
43
44int HttpServer::bind_and_start(const agent::IndexAgentPtr &index_agent,
45 const query::QueryAgentPtr &query_agent,
46 const admin::AdminAgentPtr &admin_agent,
47 const std::string &version) {
48 auto *request_handler =
49 new ProximaRequestHandler(index_agent, query_agent, admin_agent);
50 if (!request_handler) {
51 LOG_ERROR("Create proxima request handler failed.");
52 return ErrorCode_RuntimeError;
53 }
54
55 // Set server version
56 request_handler->set_version(version);
57 server_.set_version(version);
58
59 // Register http service
60 int ret = server_.AddService(
61 (proto::HttpProximaService *)request_handler, brpc::SERVER_OWNS_SERVICE,
62 // HTTP:
63 // GET /v1/collection/{collection}
64 // POST /v1/collection/{collection}
65 // PUT /v1/collection/{collection}, Not implement yet
66 // DEL /v1/collection/{collection}
67 "/v1/collection/* => collection,"
68 // HTTP: GET /v1/collection/{collection}/stats
69 "/v1/collection/*/stats => stats_collection,"
70 // HTTP: POST /v1/collection/{collection}/index
71 "/v1/collection/*/index => write,"
72 // HTTP: GET /v1/collection/{collection}/doc?key={primary_key}
73 "/v1/collection/*/doc => get_document_by_key,"
74 // HTTP: POST /v1/collection/{collection}/query
75 "/v1/collection/*/query => query,"
76 // HTTP: GET /v1/collections?repository={repository}
77 "/v1/collections => list_collections,"
78 // HTTP: GET /version
79 "/service_version => get_version");
80
81 if (ret != 0) {
82 LOG_ERROR("Http server add service failed.");
83 return ret;
84 }
85
86 // set server version
87 // server_.set_version(GetVersion());
88
89 // async start http server in single thread
90 thread_ = std::unique_ptr<std::thread>(
91 new std::thread(&HttpServer::start_server, this));
92
93 // sleep 1s
94 std::this_thread::sleep_for(std::chrono::seconds(1));
95
96 return 0;
97}
98
99int HttpServer::stop() {
100 this->stop_server();
101 if (thread_ != nullptr) {
102 thread_->join();
103 thread_ = nullptr;
104 }
105 return 0;
106}
107
108bool HttpServer::is_running() {
109 return server_.IsRunning();
110}
111
112int HttpServer::start_server() {
113 brpc::ServerOptions options;
114
115 // Do not set auto concurrency limiter, it's unstable
116 // max_concurrency | idle_timeout_sec options not open now
117
118 // Configured by query thread count,
119 // the pthread pool is shared in global.
120 // We config query thread count + 1, just for preserving
121 // one thread for scheduler.
122 options.num_threads = Config::Instance().get_query_thread_count() + 1;
123 uint32_t listen_port = Config::Instance().get_http_listen_port();
124 int ret = server_.Start(listen_port, &options);
125 if (ret != 0) {
126 LOG_ERROR("Http server start failed.");
127 return ret;
128 }
129
130 LOG_INFO("Http server start success. port[%u]", listen_port);
131
132 while (server_.IsRunning()) {
133 std::this_thread::sleep_for(std::chrono::seconds(1));
134 }
135
136 LOG_INFO("Http server thread exit.");
137 return 0;
138}
139
140int HttpServer::stop_server() {
141 server_.Stop(0);
142 server_.Join();
143 return 0;
144}
145
146
147} // end namespace server
148} // namespace be
149} // end namespace proxima
150