Merge branch '2.3' into 2.4
This commit is contained in:
		| @ -1259,7 +1259,7 @@ mxs_pcre2_result_t modutil_mysql_wildcard_match(const char* pattern, const char* | ||||
|     return rval; | ||||
| } | ||||
|  | ||||
| static inline bool is_next(mxs::Buffer::iterator it, mxs::Buffer::iterator end, const std::string& str) | ||||
| static inline bool is_next(uint8_t* it, uint8_t* end, const std::string& str) | ||||
| { | ||||
|     mxb_assert(it != end); | ||||
|     for (auto s_it = str.begin(); s_it != str.end(); ++s_it, ++it) | ||||
| @ -1316,12 +1316,11 @@ static const LUT is_special([](uint8_t c) { | ||||
|                                     c) != std::string::npos; | ||||
|                             }); | ||||
|  | ||||
| static std::pair<bool, mxs::Buffer::iterator> probe_number(mxs::Buffer::iterator it, | ||||
|                                                            mxs::Buffer::iterator end) | ||||
| static inline std::pair<bool, uint8_t*> probe_number(uint8_t* it, uint8_t* end) | ||||
| { | ||||
|     mxb_assert(it != end); | ||||
|     mxb_assert(is_digit(*it)); | ||||
|     std::pair<bool, mxs::Buffer::iterator> rval = std::make_pair(true, it); | ||||
|     std::pair<bool, uint8_t*> rval = std::make_pair(true, it); | ||||
|     bool is_hex = *it == '0'; | ||||
|     bool allow_hex = false; | ||||
|  | ||||
| @ -1348,7 +1347,7 @@ static std::pair<bool, mxs::Buffer::iterator> probe_number(mxs::Buffer::iterator | ||||
|             else if (*it == 'e') | ||||
|             { | ||||
|                 // Possible scientific notation number | ||||
|                 auto next_it = std::next(it); | ||||
|                 auto next_it = it + 1; | ||||
|  | ||||
|                 if (next_it == end || (!is_digit(*next_it) && *next_it != '-')) | ||||
|                 { | ||||
| @ -1365,7 +1364,7 @@ static std::pair<bool, mxs::Buffer::iterator> probe_number(mxs::Buffer::iterator | ||||
|             else if (*it == '.') | ||||
|             { | ||||
|                 // Possible decimal number | ||||
|                 auto next_it = std::next(it); | ||||
|                 auto next_it = it + 1; | ||||
|  | ||||
|                 if (next_it != end && !is_digit(*next_it)) | ||||
|                 { | ||||
| @ -1415,7 +1414,7 @@ static inline bool is_negation(const std::string& str, int i) | ||||
|     return rval; | ||||
| } | ||||
|  | ||||
| mxs::Buffer::iterator find_char(mxs::Buffer::iterator it, const mxs::Buffer::iterator& end, char c) | ||||
| static inline uint8_t* find_char(uint8_t* it, uint8_t* end, char c) | ||||
| { | ||||
|     for (; it != end; ++it) | ||||
|     { | ||||
| @ -1440,13 +1439,13 @@ namespace maxscale | ||||
|  | ||||
| std::string get_canonical(GWBUF* querybuf) | ||||
| { | ||||
|     std::string rval; | ||||
|     mxb_assert(GWBUF_IS_CONTIGUOUS(querybuf)); | ||||
|     uint8_t* it = GWBUF_DATA(querybuf) + MYSQL_HEADER_LEN + 1; | ||||
|     uint8_t* end = GWBUF_DATA(querybuf) + gwbuf_length(querybuf); | ||||
|     std::string rval(end - it, 0); | ||||
|     int i = 0; | ||||
|     rval.resize(gwbuf_length(querybuf) - MYSQL_HEADER_LEN + 1); | ||||
|     mxs::Buffer buf(querybuf); | ||||
|  | ||||
|     for (auto it = std::next(buf.begin(), MYSQL_HEADER_LEN + 1);    // Skip packet header and command | ||||
|          it != buf.end(); ++it) | ||||
|     for (; it != end; ++it) | ||||
|     { | ||||
|         if (!is_special(*it)) | ||||
|         { | ||||
| @ -1456,9 +1455,9 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|         else if (*it == '\\') | ||||
|         { | ||||
|             // Jump over any escaped values | ||||
|             rval[i++] += *it++; | ||||
|             rval[i++] = *it++; | ||||
|  | ||||
|             if (it != buf.end()) | ||||
|             if (it != end) | ||||
|             { | ||||
|                 rval[i++] = *it; | ||||
|             } | ||||
| @ -1479,19 +1478,19 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|                 rval[i++] = ' '; | ||||
|             } | ||||
|         } | ||||
|         else if (*it == '/' && is_next(it, buf.end(), "/*")) | ||||
|         else if (*it == '/' && is_next(it, end, "/*")) | ||||
|         { | ||||
|             auto comment_start = std::next(it, 2); | ||||
|             if (comment_start == buf.end()) | ||||
|             if (comment_start == end) | ||||
|             { | ||||
|                 break; | ||||
|             } | ||||
|             else if (*comment_start != '!' && *comment_start != 'M') | ||||
|             { | ||||
|                 // Non-executable comment | ||||
|                 while (it != buf.end()) | ||||
|                 while (it != end) | ||||
|                 { | ||||
|                     if (is_next(it, buf.end(), "*/")) | ||||
|                     if (is_next(it, end, "*/")) | ||||
|                     { | ||||
|                         // Comment end marker, return to normal parsing | ||||
|                         ++it; | ||||
| @ -1500,7 +1499,7 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|                     ++it; | ||||
|                 } | ||||
|  | ||||
|                 if (it == buf.end()) | ||||
|                 if (it == end) | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
| @ -1512,10 +1511,10 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|             } | ||||
|         } | ||||
|         else if ((*it == '#' || *it == '-') | ||||
|                  && (is_next(it, buf.end(), "# ") || is_next(it, buf.end(), "-- "))) | ||||
|                  && (is_next(it, end, "# ") || is_next(it, end, "-- "))) | ||||
|         { | ||||
|             // End-of-line comment, jump to the next line if one exists | ||||
|             while (it != buf.end()) | ||||
|             while (it != end) | ||||
|             { | ||||
|                 if (*it == '\n') | ||||
|                 { | ||||
| @ -1523,7 +1522,7 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|                 } | ||||
|                 else if (*it == '\r') | ||||
|                 { | ||||
|                     if ((is_next(it, buf.end(), "\r\n"))) | ||||
|                     if ((is_next(it, end, "\r\n"))) | ||||
|                     { | ||||
|                         ++it; | ||||
|                     } | ||||
| @ -1533,14 +1532,14 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|                 ++it; | ||||
|             } | ||||
|  | ||||
|             if (it == buf.end()) | ||||
|             if (it == end) | ||||
|             { | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         else if (is_digit(*it) && (i == 0 || (!is_alnum(rval[i - 1]) && rval[i - 1] != '_'))) | ||||
|         { | ||||
|             auto num_end = probe_number(it, buf.end()); | ||||
|             auto num_end = probe_number(it, end); | ||||
|  | ||||
|             if (num_end.first) | ||||
|             { | ||||
| @ -1556,7 +1555,7 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|         else if (*it == '\'' || *it == '"') | ||||
|         { | ||||
|             char c = *it; | ||||
|             if ((it = find_char(std::next(it), buf.end(), c)) == buf.end()) | ||||
|             if ((it = find_char(it + 1, end, c)) == end) | ||||
|             { | ||||
|                 break; | ||||
|             } | ||||
| @ -1565,7 +1564,7 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|         else if (*it == '`') | ||||
|         { | ||||
|             auto start = it; | ||||
|             if ((it = find_char(std::next(it), buf.end(), '`')) == buf.end()) | ||||
|             if ((it = find_char(it + 1, end, '`')) == end) | ||||
|             { | ||||
|                 break; | ||||
|             } | ||||
| @ -1578,7 +1577,7 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|             rval[i++] = *it; | ||||
|         } | ||||
|  | ||||
|         mxb_assert(it != buf.end()); | ||||
|         mxb_assert(it != end); | ||||
|     } | ||||
|  | ||||
|     // Remove trailing whitespace | ||||
| @ -1590,8 +1589,6 @@ std::string get_canonical(GWBUF* querybuf) | ||||
|     // Shrink the buffer so that the internal bookkeeping of std::string remains up to date | ||||
|     rval.resize(i); | ||||
|  | ||||
|     buf.release(); | ||||
|  | ||||
|     return rval; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -208,6 +208,24 @@ void ResultSet::write(DCB* dcb) | ||||
|     mysql_send_eof(dcb, seqno); | ||||
| } | ||||
|  | ||||
| json_t* ResultSet::get_json_value(const std::string& s) | ||||
| { | ||||
|     json_t* js; | ||||
|     char* end; | ||||
|     long l = strtol(s.c_str(), &end, 10); | ||||
|  | ||||
|     if (end != s.c_str() && *end == '\0') | ||||
|     { | ||||
|         js = json_integer(l); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         js = json_string(s.c_str()); | ||||
|     } | ||||
|  | ||||
|     return js; | ||||
| } | ||||
|  | ||||
| void ResultSet::write_as_json(DCB* dcb) | ||||
| { | ||||
|     json_t* arr = json_array(); | ||||
| @ -218,7 +236,7 @@ void ResultSet::write_as_json(DCB* dcb) | ||||
|  | ||||
|         for (size_t i = 0; i < row.size(); i++) | ||||
|         { | ||||
|             json_object_set_new(obj, m_columns[i].c_str(), json_string(row[i].c_str())); | ||||
|             json_object_set_new(obj, m_columns[i].c_str(), get_json_value(row[i])); | ||||
|         } | ||||
|  | ||||
|         json_array_append_new(arr, obj); | ||||
| @ -227,4 +245,6 @@ void ResultSet::write_as_json(DCB* dcb) | ||||
|     char* js = json_dumps(arr, JSON_INDENT(4)); | ||||
|     dcb_printf(dcb, "%s", js); | ||||
|     MXS_FREE(js); | ||||
|  | ||||
|     json_decref(arr); | ||||
| } | ||||
|  | ||||
| @ -62,7 +62,7 @@ struct | ||||
|     uint64_t                  next_session_id; | ||||
|     uint32_t                  retain_last_statements; | ||||
|     session_dump_statements_t dump_statements; | ||||
|     uint32_t session_trace; | ||||
|     uint32_t                  session_trace; | ||||
| } this_unit = | ||||
| { | ||||
|     1, | ||||
| @ -160,7 +160,6 @@ bool session_start(MXS_SESSION* session) | ||||
|  | ||||
|     session->state = SESSION_STATE_STARTED; | ||||
|     mxb::atomic::add(&session->service->stats.n_sessions, 1, mxb::atomic::RELAXED); | ||||
|     mxb::atomic::add(&session->service->stats.n_current, 1, mxb::atomic::RELAXED); | ||||
|  | ||||
|     MXS_INFO("Started %s client session [%" PRIu64 "] for '%s' from %s", | ||||
|              session->service->name(), session->ses_id, | ||||
| @ -279,8 +278,6 @@ static void session_final_free(MXS_SESSION* ses) | ||||
|  | ||||
|     session->state = SESSION_STATE_TO_BE_FREED; | ||||
|  | ||||
|     mxb::atomic::add(&session->service->stats.n_current, -1, mxb::atomic::RELAXED); | ||||
|  | ||||
|     if (session->client_dcb) | ||||
|     { | ||||
|         dcb_free_all_memory(session->client_dcb); | ||||
| @ -1162,6 +1159,9 @@ Session::Session(const SListener& listener) | ||||
|     { | ||||
|         m_retain_last_statements = this_unit.retain_last_statements; | ||||
|     } | ||||
|  | ||||
|     mxb::atomic::add(&service->stats.n_current, 1, mxb::atomic::RELAXED); | ||||
|     mxb_assert(service->stats.n_current >= 0); | ||||
| } | ||||
|  | ||||
| Session::~Session() | ||||
| @ -1176,6 +1176,9 @@ Session::~Session() | ||||
|         f.filter->obj->closeSession(f.instance, f.session); | ||||
|         f.filter->obj->freeSession(f.instance, f.session); | ||||
|     } | ||||
|  | ||||
|     mxb::atomic::add(&service->stats.n_current, -1, mxb::atomic::RELAXED); | ||||
|     mxb_assert(service->stats.n_current >= 0); | ||||
| } | ||||
|  | ||||
| void Session::set_client_dcb(DCB* dcb) | ||||
| @ -1696,6 +1699,6 @@ void Session::dump_session_log() | ||||
|             log += s; | ||||
|         } | ||||
|  | ||||
|         MXS_NOTICE("Session log for session (%" PRIu64"): \n%s ", ses_id, log.c_str()); | ||||
|         MXS_NOTICE("Session log for session (%" PRIu64 "): \n%s ", ses_id, log.c_str()); | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| add_executable(profile_trxboundaryparser profile_trxboundaryparser.cc) | ||||
| add_executable(profile_get_canonical profile_get_canonical.cc) | ||||
| add_executable(test_adminusers test_adminusers.cc) | ||||
| add_executable(test_atomic test_atomic.cc) | ||||
| add_executable(test_buffer test_buffer.cc) | ||||
| @ -28,6 +29,7 @@ add_executable(test_utils test_utils.cc) | ||||
| add_executable(test_session_track test_session_track.cc) | ||||
|  | ||||
| target_link_libraries(profile_trxboundaryparser maxscale-common) | ||||
| target_link_libraries(profile_get_canonical maxscale-common) | ||||
| target_link_libraries(test_adminusers maxscale-common) | ||||
| target_link_libraries(test_atomic maxscale-common) | ||||
| target_link_libraries(test_buffer maxscale-common) | ||||
|  | ||||
							
								
								
									
										46
									
								
								server/core/test/profile_get_canonical.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								server/core/test/profile_get_canonical.cc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| /* | ||||
|  * Copyright (c) 2016 MariaDB Corporation Ab | ||||
|  * | ||||
|  * Use of this software is governed by the Business Source License included | ||||
|  * in the LICENSE.TXT file and at www.mariadb.com/bsl11. | ||||
|  * | ||||
|  * Change Date: 2022-01-01 | ||||
|  * | ||||
|  * On the date above, in accordance with the Business Source License, use | ||||
|  * of this software will be governed by version 2 or later of the General | ||||
|  * Public License. | ||||
|  */ | ||||
|  | ||||
| #include <maxscale/ccdefs.hh> | ||||
| #include <maxscale/modutil.hh> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
|  | ||||
| using Clock = std::chrono::steady_clock; | ||||
| using std::chrono::duration_cast; | ||||
| using std::chrono::milliseconds; | ||||
|  | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
|     int ITERATIONS = 10000000; | ||||
|  | ||||
|     for (std::string line; std::getline(std::cin, line);) | ||||
|     { | ||||
|         GWBUF* buf = modutil_create_query(line.c_str()); | ||||
|         auto start = Clock::now(); | ||||
|  | ||||
|         for (int i = 0; i < ITERATIONS; i++) | ||||
|         { | ||||
|             auto str = mxs::get_canonical(buf); | ||||
|         } | ||||
|  | ||||
|         auto end = Clock::now(); | ||||
|         gwbuf_free(buf); | ||||
|  | ||||
|         std::cout << line << "\n" | ||||
|                   << duration_cast<milliseconds>(end - start).count() << "ms\n\n"; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @ -26,8 +26,6 @@ Session::Session(Client* pClient, const SListener& listener) | ||||
| { | ||||
|     MXS_SESSION* pSession = this; | ||||
|  | ||||
|     memset((void*)pSession, 0, sizeof(MXS_SESSION)); | ||||
|  | ||||
|     pSession->state = SESSION_STATE_CREATED; | ||||
|  | ||||
|     pSession->client_dcb = &m_client_dcb; | ||||
|  | ||||
| @ -1419,13 +1419,15 @@ static void worker_func(int thread_id, void* data) | ||||
|     for (TargetList::iterator it = info->targets.begin(); | ||||
|          it != info->targets.end(); it++) | ||||
|     { | ||||
|         LocalClient* client = LocalClient::create(&info->session, &info->protocol, it->first); | ||||
|         GWBUF* buffer = modutil_create_query(it->second.c_str()); | ||||
|         client->queue_query(buffer); | ||||
|         gwbuf_free(buffer); | ||||
|         if (LocalClient* client = LocalClient::create(&info->session, &info->protocol, it->first)) | ||||
|         { | ||||
|             GWBUF* buffer = modutil_create_query(it->second.c_str()); | ||||
|             client->queue_query(buffer); | ||||
|             gwbuf_free(buffer); | ||||
|  | ||||
|         // The LocalClient needs to delete itself once the queries are done | ||||
|         client->self_destruct(); | ||||
|             // The LocalClient needs to delete itself once the queries are done | ||||
|             client->self_destruct(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     delete info; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Markus Mäkelä
					Markus Mäkelä