nghttpx: Use doubly linked list for dconns_ and streams_
This commit is contained in:
parent
d34095cf49
commit
0f87cedc2d
|
@ -44,8 +44,8 @@ namespace shrpx {
|
||||||
|
|
||||||
Http2DownstreamConnection::Http2DownstreamConnection(
|
Http2DownstreamConnection::Http2DownstreamConnection(
|
||||||
DownstreamConnectionPool *dconn_pool, Http2Session *http2session)
|
DownstreamConnectionPool *dconn_pool, Http2Session *http2session)
|
||||||
: DownstreamConnection(dconn_pool), http2session_(http2session),
|
: DownstreamConnection(dconn_pool), dlnext(nullptr), dlprev(nullptr),
|
||||||
sd_(nullptr) {}
|
http2session_(http2session), sd_(nullptr) {}
|
||||||
|
|
||||||
Http2DownstreamConnection::~Http2DownstreamConnection() {
|
Http2DownstreamConnection::~Http2DownstreamConnection() {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
|
|
@ -74,6 +74,8 @@ public:
|
||||||
int submit_rst_stream(Downstream *downstream,
|
int submit_rst_stream(Downstream *downstream,
|
||||||
uint32_t error_code = NGHTTP2_INTERNAL_ERROR);
|
uint32_t error_code = NGHTTP2_INTERNAL_ERROR);
|
||||||
|
|
||||||
|
Http2DownstreamConnection *dlnext, *dlprev;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Http2Session *http2session_;
|
Http2Session *http2session_;
|
||||||
StreamData *sd_;
|
StreamData *sd_;
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "template.h"
|
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
|
||||||
|
@ -208,13 +207,11 @@ int Http2Session::disconnect(bool hard) {
|
||||||
// this object. In order to achieve this, we first swap dconns_ and
|
// this object. In order to achieve this, we first swap dconns_ and
|
||||||
// streams_. Upstream::on_downstream_reset() may add
|
// streams_. Upstream::on_downstream_reset() may add
|
||||||
// Http2DownstreamConnection.
|
// Http2DownstreamConnection.
|
||||||
std::unordered_set<Http2DownstreamConnection *> dconns;
|
auto dconns = std::move(dconns_);
|
||||||
dconns.swap(dconns_);
|
auto streams = std::move(streams_);
|
||||||
std::unordered_set<StreamData *> streams;
|
|
||||||
streams.swap(streams_);
|
|
||||||
|
|
||||||
std::set<ClientHandler *> handlers;
|
std::set<ClientHandler *> handlers;
|
||||||
for (auto dc : dconns) {
|
for (auto dc = dconns.head; dc; dc = dc->dlnext) {
|
||||||
if (!dc->get_client_handler()) {
|
if (!dc->get_client_handler()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -226,8 +223,10 @@ int Http2Session::disconnect(bool hard) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &s : streams) {
|
for (auto s = streams.head; s;) {
|
||||||
|
auto next = s->dlnext;
|
||||||
delete s;
|
delete s;
|
||||||
|
s = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -534,17 +533,17 @@ int Http2Session::downstream_connect_proxy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Session::add_downstream_connection(Http2DownstreamConnection *dconn) {
|
void Http2Session::add_downstream_connection(Http2DownstreamConnection *dconn) {
|
||||||
dconns_.insert(dconn);
|
dconns_.append(dconn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Http2Session::remove_downstream_connection(Http2DownstreamConnection *dconn) {
|
Http2Session::remove_downstream_connection(Http2DownstreamConnection *dconn) {
|
||||||
dconns_.erase(dconn);
|
dconns_.remove(dconn);
|
||||||
dconn->detach_stream_data();
|
dconn->detach_stream_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Session::remove_stream_data(StreamData *sd) {
|
void Http2Session::remove_stream_data(StreamData *sd) {
|
||||||
streams_.erase(sd);
|
streams_.remove(sd);
|
||||||
if (sd->dconn) {
|
if (sd->dconn) {
|
||||||
sd->dconn->detach_stream_data();
|
sd->dconn->detach_stream_data();
|
||||||
}
|
}
|
||||||
|
@ -556,6 +555,7 @@ int Http2Session::submit_request(Http2DownstreamConnection *dconn, int32_t pri,
|
||||||
const nghttp2_data_provider *data_prd) {
|
const nghttp2_data_provider *data_prd) {
|
||||||
assert(state_ == CONNECTED);
|
assert(state_ == CONNECTED);
|
||||||
auto sd = make_unique<StreamData>();
|
auto sd = make_unique<StreamData>();
|
||||||
|
sd->dlnext = sd->dlprev = nullptr;
|
||||||
// TODO Specify nullptr to pri_spec for now
|
// TODO Specify nullptr to pri_spec for now
|
||||||
auto stream_id =
|
auto stream_id =
|
||||||
nghttp2_submit_request(session_, nullptr, nva, nvlen, data_prd, sd.get());
|
nghttp2_submit_request(session_, nullptr, nva, nvlen, data_prd, sd.get());
|
||||||
|
@ -567,7 +567,7 @@ int Http2Session::submit_request(Http2DownstreamConnection *dconn, int32_t pri,
|
||||||
|
|
||||||
dconn->attach_stream_data(sd.get());
|
dconn->attach_stream_data(sd.get());
|
||||||
dconn->get_downstream()->set_downstream_stream_id(stream_id);
|
dconn->get_downstream()->set_downstream_stream_id(stream_id);
|
||||||
streams_.insert(sd.release());
|
streams_.append(sd.release());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1498,7 +1498,7 @@ void Http2Session::connection_alive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Session::submit_pending_requests() {
|
void Http2Session::submit_pending_requests() {
|
||||||
for (auto dconn : dconns_) {
|
for (auto dconn = dconns_.head; dconn; dconn = dconn->dlnext) {
|
||||||
auto downstream = dconn->get_downstream();
|
auto downstream = dconn->get_downstream();
|
||||||
|
|
||||||
if (!downstream || !downstream->request_submission_ready()) {
|
if (!downstream || !downstream->request_submission_ready()) {
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#include "shrpx_connection.h"
|
#include "shrpx_connection.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ class Worker;
|
||||||
class ConnectBlocker;
|
class ConnectBlocker;
|
||||||
|
|
||||||
struct StreamData {
|
struct StreamData {
|
||||||
|
StreamData *dlnext, *dlprev;
|
||||||
Http2DownstreamConnection *dconn;
|
Http2DownstreamConnection *dconn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -188,8 +190,8 @@ private:
|
||||||
// connection check has started, this timer is started again and
|
// connection check has started, this timer is started again and
|
||||||
// traps PING ACK timeout.
|
// traps PING ACK timeout.
|
||||||
ev_timer connchk_timer_;
|
ev_timer connchk_timer_;
|
||||||
std::unordered_set<Http2DownstreamConnection *> dconns_;
|
DList<Http2DownstreamConnection> dconns_;
|
||||||
std::unordered_set<StreamData *> streams_;
|
DList<StreamData> streams_;
|
||||||
std::function<int(Http2Session &)> read_, write_;
|
std::function<int(Http2Session &)> read_, write_;
|
||||||
std::function<int(Http2Session &)> on_read_, on_write_;
|
std::function<int(Http2Session &)> on_read_, on_write_;
|
||||||
// Used to parse the response from HTTP proxy
|
// Used to parse the response from HTTP proxy
|
||||||
|
|
|
@ -80,6 +80,61 @@ template <typename T, typename F> bool test_flags(T t, F flags) {
|
||||||
return (t & flags) == flags;
|
return (t & flags) == flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// doubly linked list of element T*. T must have field T *dlprev and
|
||||||
|
// T *dlnext, which point to previous element and next element in the
|
||||||
|
// list respectively.
|
||||||
|
template <typename T> struct DList {
|
||||||
|
DList() : head(nullptr), tail(nullptr) {}
|
||||||
|
|
||||||
|
DList(const DList &) = delete;
|
||||||
|
|
||||||
|
DList &operator=(const DList &) = delete;
|
||||||
|
|
||||||
|
DList(DList &&other) : head(other.head), tail(other.tail) {
|
||||||
|
other.head = other.tail = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DList &operator=(DList &&other) {
|
||||||
|
if (this == &other) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
head = other.head;
|
||||||
|
tail = other.tail;
|
||||||
|
other.head = other.tail = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(T *t) {
|
||||||
|
if (tail) {
|
||||||
|
tail->dlnext = t;
|
||||||
|
t->dlprev = tail;
|
||||||
|
tail = t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
head = tail = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(T *t) {
|
||||||
|
auto p = t->dlprev;
|
||||||
|
auto n = t->dlnext;
|
||||||
|
if (p) {
|
||||||
|
p->dlnext = n;
|
||||||
|
}
|
||||||
|
if (head == t) {
|
||||||
|
head = n;
|
||||||
|
}
|
||||||
|
if (n) {
|
||||||
|
n->dlprev = p;
|
||||||
|
}
|
||||||
|
if (tail == t) {
|
||||||
|
tail = p;
|
||||||
|
}
|
||||||
|
t->dlprev = t->dlnext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *head, *tail;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
||||||
#endif // TEMPLATE_H
|
#endif // TEMPLATE_H
|
||||||
|
|
Loading…
Reference in New Issue