Skip to content

Commit f839a74

Browse files
authored
Make HttpSM server reference a Transaction instead of a Session (#7849)
1 parent 01d2150 commit f839a74

29 files changed

+843
-491
lines changed

iocore/net/libinknet_stub.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
limitations under the License.
2222
*/
2323

24-
#include "HttpSessionManager.h"
24+
class EThread;
25+
class Continuation;
2526
void
2627
initialize_thread_for_http_sessions(EThread *, int)
2728
{
28-
ink_assert(false);
2929
}
3030

3131
#include "P_UnixNet.h"

proxy/PoolableSession.h

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ class PoolableSession : public ProxySession
3333
public:
3434
enum PooledState {
3535
INIT,
36-
SSN_IN_USE, // actively in use
37-
KA_RESERVED, // stuck to client
38-
KA_POOLED, // free for reuse
36+
SSN_IN_USE, // actively in use
37+
KA_RESERVED, // stuck to client
38+
KA_POOLED, // free for reuse
39+
SSN_CLOSED, // Session ready to be freed
40+
SSN_TO_RELEASE // Session reaady to be released
3941
};
4042

4143
/// Hash map descriptor class for IP map.
@@ -72,18 +74,30 @@ class PoolableSession : public ProxySession
7274
TSServerSessionSharingMatchMask sharing_match = TS_SERVER_SESSION_SHARING_MATCH_MASK_NONE;
7375
TSServerSessionSharingPoolType sharing_pool = TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
7476

75-
// Keep track of connection limiting and a pointer to the
76-
// singleton that keeps track of the connection counts.
77-
OutboundConnTrack::Group *conn_track_group = nullptr;
77+
void enable_outbound_connection_tracking(OutboundConnTrack::Group *group);
78+
void release_outbound_connection_tracking();
79+
80+
void attach_hostname(const char *hostname);
7881

7982
void set_active();
8083
bool is_active();
8184
void set_private(bool new_private = true);
8285
bool is_private() const;
8386

84-
void set_netvc(NetVConnection *newvc);
87+
virtual void set_netvc(NetVConnection *newvc);
8588

86-
virtual IOBufferReader *get_reader() = 0;
89+
// Used to determine whether the session is for parent proxy
90+
// it is session to origin server
91+
// We need to determine whether a closed connection was to
92+
// close parent proxy to update the
93+
// proxy.process.http.current_parent_proxy_connections
94+
bool to_parent_proxy = false;
95+
96+
// Keep track of connection limiting and a pointer to the
97+
// singleton that keeps track of the connection counts.
98+
OutboundConnTrack::Group *conn_track_group = nullptr;
99+
100+
virtual IOBufferReader *get_remote_reader() = 0;
87101

88102
private:
89103
// Sessions become if authentication headers
@@ -192,3 +206,34 @@ PoolableSession::FQDNLinkage::equal(CryptoHash const &lhs, CryptoHash const &rhs
192206
{
193207
return lhs == rhs;
194208
}
209+
210+
inline void
211+
PoolableSession::enable_outbound_connection_tracking(OutboundConnTrack::Group *group)
212+
{
213+
ink_assert(nullptr == conn_track_group);
214+
conn_track_group = group;
215+
}
216+
217+
inline void
218+
PoolableSession::release_outbound_connection_tracking()
219+
{
220+
// Update upstream connection tracking data if present.
221+
if (conn_track_group) {
222+
if (conn_track_group->_count >= 0) {
223+
(conn_track_group->_count)--;
224+
conn_track_group = nullptr;
225+
} else {
226+
// A bit dubious, as there's no guarantee it's still negative, but even that would be interesting to know.
227+
Error("[http_ss] [%" PRId64 "] number of connections should be greater than or equal to zero: %u", con_id,
228+
conn_track_group->_count.load());
229+
}
230+
}
231+
}
232+
233+
inline void
234+
PoolableSession::attach_hostname(const char *hostname)
235+
{
236+
if (CRYPTO_HASH_ZERO == hostname_hash) {
237+
CryptoContext().hash_immediate(hostname_hash, (unsigned char *)hostname, strlen(hostname));
238+
}
239+
}

proxy/ProxySession.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ class ProxySession : public VConnection, public PluginUserArgs<TS_USER_ARGS_SSN>
107107
virtual void hook_add(TSHttpHookID id, INKContInternal *cont);
108108

109109
virtual bool is_chunked_encoding_supported() const;
110-
111110
virtual void set_half_close_flag(bool flag);
112111
virtual bool get_half_close_flag() const;
113112

@@ -137,7 +136,7 @@ class ProxySession : public VConnection, public PluginUserArgs<TS_USER_ARGS_SSN>
137136
void clear_session_active();
138137
bool is_active() const;
139138
bool is_draining() const;
140-
bool is_client_closed() const;
139+
bool is_peer_closed() const;
141140

142141
int64_t connection_id() const;
143142
TSHttpHookID get_hookid() const;
@@ -157,6 +156,12 @@ class ProxySession : public VConnection, public PluginUserArgs<TS_USER_ARGS_SSN>
157156
void do_io_shutdown(ShutdownHowTo_t howto) override;
158157
void reenable(VIO *vio) override;
159158

159+
virtual ProxyTransaction *
160+
new_transaction()
161+
{
162+
return nullptr;
163+
}
164+
160165
////////////////////
161166
// Members
162167

@@ -236,7 +241,7 @@ ProxySession::is_draining() const
236241
}
237242

238243
inline bool
239-
ProxySession::is_client_closed() const
244+
ProxySession::is_peer_closed() const
240245
{
241246
return get_netvc() == nullptr;
242247
}

proxy/ProxyTransaction.cc

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ ProxyTransaction::new_transaction(bool from_early_data)
5757
}
5858
}
5959

60-
this->increment_client_transactions_stat();
61-
_sm->attach_client_session(this, _reader);
60+
this->increment_transactions_stat();
61+
_sm->attach_client_session(this);
6262
}
6363

6464
bool
@@ -181,7 +181,7 @@ void
181181
ProxyTransaction::transaction_done()
182182
{
183183
SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
184-
this->decrement_client_transactions_stat();
184+
this->decrement_transactions_stat();
185185
}
186186

187187
// Implement VConnection interface.
@@ -221,6 +221,18 @@ ProxyTransaction::has_request_body(int64_t request_content_length, bool is_chunk
221221
return request_content_length > 0 || is_chunked;
222222
}
223223

224+
void
225+
ProxyTransaction::attach_transaction(HttpSM *attach_sm)
226+
{
227+
_sm = attach_sm;
228+
}
229+
230+
HTTPVersion
231+
ProxyTransaction::get_version(HTTPHdr &hdr) const
232+
{
233+
return hdr.version_get();
234+
}
235+
224236
bool
225237
ProxyTransaction::allow_half_open() const
226238
{

proxy/ProxyTransaction.h

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,11 @@ class ProxyTransaction : public VConnection
3939
/// Virtual Methods
4040
//
4141
virtual void new_transaction(bool from_early_data = false);
42+
virtual void attach_transaction(HttpSM *attach_sm);
4243
virtual bool attach_server_session(PoolableSession *ssession, bool transaction_done = true);
4344
Action *adjust_thread(Continuation *cont, int event, void *data);
44-
virtual void release(IOBufferReader *r) = 0;
45-
virtual void transaction_done();
45+
virtual void release() = 0;
46+
virtual void transaction_done() = 0;
4647

4748
virtual void set_active_timeout(ink_hrtime timeout_in);
4849
virtual void set_inactivity_timeout(ink_hrtime timeout_in);
@@ -63,8 +64,9 @@ class ProxyTransaction : public VConnection
6364
virtual int get_transaction_priority_weight() const;
6465
virtual int get_transaction_priority_dependence() const;
6566
virtual bool allow_half_open() const;
66-
virtual void increment_client_transactions_stat() = 0;
67-
virtual void decrement_client_transactions_stat() = 0;
67+
68+
virtual void increment_transactions_stat() = 0;
69+
virtual void decrement_transactions_stat() = 0;
6870

6971
virtual NetVConnection *get_netvc() const;
7072
virtual bool is_first_transaction() const;
@@ -85,6 +87,10 @@ class ProxyTransaction : public VConnection
8587
// Returns true if there is a request body for this request
8688
virtual bool has_request_body(int64_t content_length, bool is_chunked_set) const;
8789

90+
sockaddr const *get_remote_addr() const;
91+
92+
virtual HTTPVersion get_version(HTTPHdr &hdr) const;
93+
8894
/// Non-Virtual Methods
8995
//
9096
const char *get_protocol_string();
@@ -114,15 +120,17 @@ class ProxyTransaction : public VConnection
114120
// This function must return a non-negative number that is different for two in-progress transactions with the same proxy_ssn
115121
// session.
116122
//
117-
void set_rx_error_code(ProxyError e);
118-
void set_tx_error_code(ProxyError e);
123+
virtual void set_rx_error_code(ProxyError e);
124+
virtual void set_tx_error_code(ProxyError e);
119125

120126
bool support_sni() const;
121127

122128
/// Variables
123129
//
124130
HttpSessionAccept::Options upstream_outbound_options; // overwritable copy of options
125131

132+
IOBufferReader *get_remote_reader();
133+
126134
protected:
127135
ProxySession *_proxy_ssn = nullptr;
128136
HttpSM *_sm = nullptr;
@@ -274,3 +282,19 @@ ProxyTransaction::adjust_thread(Continuation *cont, int event, void *data)
274282
}
275283
return nullptr;
276284
}
285+
286+
inline IOBufferReader *
287+
ProxyTransaction::get_remote_reader()
288+
{
289+
return _reader;
290+
}
291+
292+
inline sockaddr const *
293+
ProxyTransaction::get_remote_addr() const
294+
{
295+
if (_proxy_ssn) {
296+
return _proxy_ssn->get_remote_addr();
297+
} else {
298+
return nullptr;
299+
}
300+
}

proxy/http/Http1ClientSession.cc

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ ClassAllocator<Http1ClientSession, true> http1ClientSessionAllocator("http1Clien
6161

6262
Http1ClientSession::Http1ClientSession() : super(), trans(this) {}
6363

64+
//
65+
// Will only close the connection if do_io_close has been called previously (to set read_state to HCS_CLOSED
6466
void
6567
Http1ClientSession::destroy()
6668
{
@@ -86,12 +88,16 @@ Http1ClientSession::release_transaction()
8688
if (transact_count == released_transactions) {
8789
// Make sure we previously called release() or do_io_close() on the session
8890
ink_release_assert(read_state != HCS_INIT);
89-
if (read_state == HCS_ACTIVE_READER) {
91+
if (is_active()) {
9092
// (in)active timeout
9193
do_io_close(HTTP_ERRNO);
94+
} else if (read_state == HCS_ACTIVE_READER) {
95+
release(&trans); // Put back to keep-alive state
9296
} else {
9397
destroy();
9498
}
99+
} else {
100+
ink_release_assert(transact_count == released_transactions);
95101
}
96102
}
97103

@@ -209,6 +215,9 @@ void
209215
Http1ClientSession::do_io_close(int alerrno)
210216
{
211217
if (read_state == HCS_CLOSED) {
218+
if (transact_count == released_transactions) {
219+
this->destroy();
220+
}
212221
return; // Don't double call session close
213222
}
214223
if (read_state == HCS_ACTIVE_READER) {
@@ -257,8 +266,6 @@ Http1ClientSession::do_io_close(int alerrno)
257266
HTTP_SUM_DYN_STAT(http_transactions_per_client_con, transact_count);
258267
read_state = HCS_CLOSED;
259268

260-
// Can go ahead and close the netvc now, but keeping around the session object
261-
// until all the transactions are closed
262269
if (_vc) {
263270
_vc->do_io_close();
264271
_vc = nullptr;
@@ -347,11 +354,21 @@ Http1ClientSession::state_keep_alive(int event, void *data)
347354
{
348355
// Route the event. It is either for vc or
349356
// the origin server slave vc
350-
if (data && data == slave_ka_vio) {
351-
return state_slave_keep_alive(event, data);
352-
} else {
353-
ink_assert(data && data == ka_vio);
354-
ink_assert(read_state == HCS_KEEP_ALIVE);
357+
if (data) {
358+
if (data == slave_ka_vio) {
359+
return state_slave_keep_alive(event, data);
360+
} else if (data == schedule_event) {
361+
schedule_event = nullptr;
362+
} else {
363+
ink_assert(data && data == ka_vio);
364+
ink_assert(read_state == HCS_KEEP_ALIVE);
365+
}
366+
}
367+
368+
// If we got here due to a network I/O event directly, go ahead and cancel any remaining schedule events
369+
if (schedule_event) {
370+
schedule_event->cancel();
371+
schedule_event = nullptr;
355372
}
356373

357374
STATE_ENTER(&Http1ClientSession::state_keep_alive, event, data);
@@ -387,8 +404,6 @@ Http1ClientSession::state_keep_alive(int event, void *data)
387404
void
388405
Http1ClientSession::release(ProxyTransaction *trans)
389406
{
390-
ink_assert(read_state == HCS_ACTIVE_READER || read_state == HCS_INIT);
391-
392407
// When release is called from start() to read the first transaction, get_sm()
393408
// will return null.
394409
HttpSM *sm = trans->get_sm();
@@ -409,6 +424,7 @@ Http1ClientSession::release(ProxyTransaction *trans)
409424
// buffer. If there is, spin up a new state
410425
// machine to process it. Otherwise, issue an
411426
// IO to wait for new data
427+
/* Start the new transaction once we finish completely the current transaction and unroll the stack */
412428
bool more_to_read = this->_reader->is_read_avail_more_than(0);
413429
if (more_to_read) {
414430
HttpSsnDebug("[%" PRId64 "] data already in buffer, starting new transaction", con_id);
@@ -429,19 +445,19 @@ Http1ClientSession::release(ProxyTransaction *trans)
429445
}
430446
}
431447

432-
void
448+
ProxyTransaction *
433449
Http1ClientSession::new_transaction()
434450
{
435451
// If the client connection terminated during API callouts we're done.
436452
if (nullptr == _vc) {
437453
this->do_io_close(); // calls the SSN_CLOSE hooks to match the SSN_START hooks.
438-
return;
454+
return nullptr;
439455
}
440456

441457
if (!_vc->add_to_active_queue()) {
442458
// no room in the active queue close the connection
443459
this->do_io_close();
444-
return;
460+
return nullptr;
445461
}
446462

447463
// Defensive programming, make sure nothing persists across
@@ -453,6 +469,7 @@ Http1ClientSession::new_transaction()
453469
transact_count++;
454470

455471
trans.new_transaction(read_from_early_data > 0 ? true : false);
472+
return &trans;
456473
}
457474

458475
bool
@@ -472,7 +489,7 @@ Http1ClientSession::attach_server_session(PoolableSession *ssession, bool transa
472489
// have it call the client session back. This IO also prevent
473490
// the server net conneciton from calling back a dead sm
474491
SET_HANDLER(&Http1ClientSession::state_keep_alive);
475-
slave_ka_vio = ssession->do_io_read(this, INT64_MAX, ssession->get_reader()->mbuf);
492+
slave_ka_vio = ssession->do_io_read(this, INT64_MAX, ssession->get_remote_reader()->mbuf);
476493
ink_assert(slave_ka_vio != ka_vio);
477494

478495
// Transfer control of the write side as well

0 commit comments

Comments
 (0)