diff --git a/include/maxscale/session.h b/include/maxscale/session.h index c401fe9d3..d86c063e5 100644 --- a/include/maxscale/session.h +++ b/include/maxscale/session.h @@ -29,12 +29,15 @@ #ifdef __cplusplus #include +#include #include #include #include typedef std::deque > SessionStmtQueue; +typedef std::tr1::unordered_set DCBSet; #else typedef void SessionStmtQueue; +typedef void DCBSet; #endif MXS_BEGIN_DECLS @@ -211,6 +214,7 @@ typedef struct session GWBUF* buffer; /*< Buffer to deliver to up. */ } response; /*< Shortcircuited response */ SessionStmtQueue* last_statements; /*< The N last statements by the client */ + DCBSet* dcb_set; /*< Set of associated backend DCBs */ skygw_chk_t ses_chk_tail; } MXS_SESSION; diff --git a/server/core/dcb.cc b/server/core/dcb.cc index a9f7ac094..7d9612a71 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -245,7 +245,7 @@ dcb_final_free(DCB *dcb) DCB_ROLE_SERVICE_LISTENER == dcb->dcb_role || DCB_ROLE_INTERNAL == dcb->dcb_role); - session_put_ref(local_session); + session_unlink_backend_dcb(local_session, dcb); if (is_client_dcb) { @@ -464,7 +464,7 @@ dcb_connect(SERVER *server, MXS_SESSION *session, const char *protocol) MXS_DEBUG("Failed to connect to server [%s]:%d, from backend dcb %p, client dcp %p fd %d", server->address, server->port, dcb, session->client_dcb, session->client_dcb->fd); // Remove the inc ref that was done in session_link_backend_dcb(). - session_put_ref(dcb->session); + session_unlink_backend_dcb(dcb->session, dcb); dcb->session = NULL; dcb_free_all_memory(dcb); return NULL; @@ -501,7 +501,7 @@ dcb_connect(SERVER *server, MXS_SESSION *session, const char *protocol) close(dcb->fd); dcb->fd = DCBFD_CLOSED; // Remove the inc ref that was done in session_link_backend_dcb(). - session_put_ref(dcb->session); + session_unlink_backend_dcb(dcb->session, dcb); dcb->session = NULL; dcb_free_all_memory(dcb); return NULL; @@ -517,7 +517,7 @@ dcb_connect(SERVER *server, MXS_SESSION *session, const char *protocol) close(dcb->fd); dcb->fd = DCBFD_CLOSED; // Remove the inc ref that was done in session_link_backend_dcb(). - session_put_ref(dcb->session); + session_unlink_backend_dcb(dcb->session, dcb); dcb->session = NULL; dcb_free_all_memory(dcb); return NULL; @@ -1326,7 +1326,7 @@ dcb_maybe_add_persistent(DCB *dcb) CHK_SESSION(local_session); if (SESSION_STATE_DUMMY != local_session->state) { - session_put_ref(local_session); + session_unlink_backend_dcb(local_session, dcb); } } diff --git a/server/core/internal/session.h b/server/core/internal/session.h index 6867d7ba9..6fb8254d4 100644 --- a/server/core/internal/session.h +++ b/server/core/internal/session.h @@ -51,6 +51,14 @@ const char *session_state(mxs_session_state_t); */ void session_link_backend_dcb(MXS_SESSION *session, struct dcb *dcb); +/** + * Unlink a session to a backend DCB. + * + * @param session The session to unlink with the dcb + * @param dcb The backend DCB to be unlinked + */ +void session_unlink_backend_dcb(MXS_SESSION *session, struct dcb *dcb); + RESULTSET *sessionGetList(SESSIONLISTFILTER); void printAllSessions(); diff --git a/server/core/session.cc b/server/core/session.cc index 5ac85b49d..f75119c1d 100644 --- a/server/core/session.cc +++ b/server/core/session.cc @@ -106,17 +106,19 @@ MXS_SESSION* session_alloc_with_id(SERVICE *service, DCB *client_dcb, uint64_t i { MXS_SESSION *session = (MXS_SESSION *)(MXS_MALLOC(sizeof(*session))); SessionVarsByName *session_variables = new (std::nothrow) SessionVarsByName; + DCBSet* dcb_set = new (std::nothrow) DCBSet; - if ((session == NULL) || (session_variables == NULL)) + if ((session == NULL) || (session_variables == NULL) || (dcb_set == NULL)) { MXS_FREE(session); delete session_variables; - + delete dcb_set; return NULL; } session_initialize(session); session->variables = session_variables; + session->dcb_set = dcb_set; session->ses_id = id; return session_alloc_body(service, client_dcb, session); } @@ -279,6 +281,13 @@ void session_link_backend_dcb(MXS_SESSION *session, DCB *dcb) dcb->service = session->service; /** Move this DCB under the same thread */ dcb->poll.thread.id = session->client_dcb->poll.thread.id; + session->dcb_set->insert(dcb); +} + +void session_unlink_backend_dcb(MXS_SESSION *session, DCB *dcb) +{ + session->dcb_set->erase(dcb); + session_put_ref(session); } /** @@ -396,6 +405,7 @@ session_final_free(MXS_SESSION *session) delete session->variables; delete session->last_statements; + delete session->dcb_set; MXS_FREE(session); } diff --git a/server/modules/filter/test/mock_session.cc b/server/modules/filter/test/mock_session.cc index ecac686de..5a15ce7f8 100644 --- a/server/modules/filter/test/mock_session.cc +++ b/server/modules/filter/test/mock_session.cc @@ -45,6 +45,8 @@ Session::Session(Client* pClient) Session::~Session() { delete variables; + delete last_statements; + delete dcb_set; } Client& Session::client() const