diff options
Diffstat (limited to 'sql/session_tracker.cc')
-rw-r--r-- | sql/session_tracker.cc | 790 |
1 files changed, 158 insertions, 632 deletions
diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc index b73bd1d1d4a..65d600b9b5a 100644 --- a/sql/session_tracker.cc +++ b/sql/session_tracker.cc @@ -15,10 +15,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef EMBEDDED_LIBRARY #include "sql_plugin.h" -#include "session_tracker.h" - #include "hash.h" #include "table.h" #include "rpl_gtid.h" @@ -35,264 +32,12 @@ void State_tracker::mark_as_changed(THD *thd, LEX_CSTRING *tracked_item_name) } -class Not_implemented_tracker : public State_tracker -{ -public: - bool enable(THD *thd) - { return false; } - bool update(THD *, set_var *) - { return false; } - bool store(THD *, String *) - { return false; } - void mark_as_changed(THD *, LEX_CSTRING *tracked_item_name) - {} - -}; - -/** - Session_sysvars_tracker - - This is a tracker class that enables & manages the tracking of session - system variables. It internally maintains a hash of user supplied variable - references and a boolean field to store if the variable was changed by the - last statement. -*/ - -class Session_sysvars_tracker : public State_tracker -{ -private: - - struct sysvar_node_st { - sys_var *m_svar; - bool *test_load; - bool m_changed; - }; - - class vars_list - { - private: - /** - Registered system variables. (@@session_track_system_variables) - A hash to store the name of all the system variables specified by the - user. - */ - HASH m_registered_sysvars; - /** Size of buffer for string representation */ - size_t buffer_length; - myf m_mem_flag; - /** - If TRUE then we want to check all session variable. - */ - bool track_all; - void init() - { - my_hash_init(&m_registered_sysvars, - &my_charset_bin, - 4, 0, 0, (my_hash_get_key) sysvars_get_key, - my_free, MYF(HASH_UNIQUE | - ((m_mem_flag & MY_THREAD_SPECIFIC) ? - HASH_THREAD_SPECIFIC : 0))); - } - void free_hash() - { - if (my_hash_inited(&m_registered_sysvars)) - { - my_hash_free(&m_registered_sysvars); - } - } - - uchar* search(const sys_var *svar) - { - return (my_hash_search(&m_registered_sysvars, (const uchar *)&svar, - sizeof(sys_var *))); - } - - public: - vars_list() : - buffer_length(0) - { - m_mem_flag= current_thd ? MY_THREAD_SPECIFIC : 0; - init(); - } - - size_t get_buffer_length() - { - DBUG_ASSERT(buffer_length != 0); // asked earlier then should - return buffer_length; - } - ~vars_list() - { - /* free the allocated hash. */ - if (my_hash_inited(&m_registered_sysvars)) - { - my_hash_free(&m_registered_sysvars); - } - } - - uchar* insert_or_search(sysvar_node_st *node, const sys_var *svar) - { - uchar *res; - res= search(svar); - if (!res) - { - if (track_all) - { - insert(node, svar, m_mem_flag); - return search(svar); - } - } - return res; - } - - bool insert(sysvar_node_st *node, const sys_var *svar, myf mem_flag); - void reinit(); - void reset(); - inline bool is_enabled() - { - return track_all || m_registered_sysvars.records; - } - void copy(vars_list* from, THD *thd); - bool parse_var_list(THD *thd, LEX_STRING var_list, bool throw_error, - CHARSET_INFO *char_set, bool take_mutex); - bool construct_var_list(char *buf, size_t buf_len); - bool store(THD *thd, String *buf); - }; - /** - Two objects of vars_list type are maintained to manage - various operations. - */ - vars_list *orig_list, *tool_list; - -public: - Session_sysvars_tracker() - { - orig_list= new (std::nothrow) vars_list(); - tool_list= new (std::nothrow) vars_list(); - } - - ~Session_sysvars_tracker() - { - if (orig_list) - delete orig_list; - if (tool_list) - delete tool_list; - } - - size_t get_buffer_length() - { - return orig_list->get_buffer_length(); - } - bool construct_var_list(char *buf, size_t buf_len) - { - return orig_list->construct_var_list(buf, buf_len); - } - - /** - Method used to check the validity of string provided - for session_track_system_variables during the server - startup. - */ - static bool server_init_check(THD *thd, CHARSET_INFO *char_set, - LEX_STRING var_list) - { - return check_var_list(thd, var_list, false, char_set, false); - } - - static bool server_init_process(THD *thd, CHARSET_INFO *char_set, - LEX_STRING var_list) - { - vars_list dummy; - bool result; - result= dummy.parse_var_list(thd, var_list, false, char_set, false); - if (!result) - dummy.construct_var_list(var_list.str, var_list.length + 1); - return result; - } - - void reset(); - bool enable(THD *thd); - bool check_str(THD *thd, LEX_STRING *val); - bool update(THD *thd, set_var *var); - bool store(THD *thd, String *buf); - void mark_as_changed(THD *thd, LEX_CSTRING *tracked_item_name); - /* callback */ - static uchar *sysvars_get_key(const char *entry, size_t *length, - my_bool not_used __attribute__((unused))); - - // hash iterators - static my_bool name_array_filler(void *ptr, void *data_ptr); - static my_bool store_variable(void *ptr, void *data_ptr); - static my_bool reset_variable(void *ptr, void *data_ptr); - - static bool check_var_list(THD *thd, LEX_STRING var_list, bool throw_error, - CHARSET_INFO *char_set, bool take_mutex); -}; - - - -/** - Current_schema_tracker, - - This is a tracker class that enables & manages the tracking of current - schema for a particular connection. -*/ - -class Current_schema_tracker : public State_tracker -{ -private: - bool schema_track_inited; - void reset(); - -public: - - Current_schema_tracker() - { - schema_track_inited= false; - } - - bool enable(THD *thd) - { return update(thd, NULL); } - bool update(THD *thd, set_var *var); - bool store(THD *thd, String *buf); -}; - -/* - Session_state_change_tracker - - This is a boolean tracker class that will monitor any change that contributes - to a session state change. - Attributes that contribute to session state change include: - - Successful change to System variables - - User defined variables assignments - - temporary tables created, altered or deleted - - prepared statements added or removed - - change in current database - - change of current role -*/ - -class Session_state_change_tracker : public State_tracker -{ -private: - - void reset(); - -public: - Session_state_change_tracker(); - bool enable(THD *thd) - { return update(thd, NULL); }; - bool update(THD *thd, set_var *var); - bool store(THD *thd, String *buf); - bool is_state_changed(THD*); -}; - - /* To be used in expanding the buffer. */ static const unsigned int EXTRA_ALLOC= 1024; void Session_sysvars_tracker::vars_list::reinit() { - buffer_length= 0; track_all= 0; if (m_registered_sysvars.records) my_hash_reset(&m_registered_sysvars); @@ -310,10 +55,8 @@ void Session_sysvars_tracker::vars_list::reinit() void Session_sysvars_tracker::vars_list::copy(vars_list* from, THD *thd) { - reinit(); track_all= from->track_all; free_hash(); - buffer_length= from->buffer_length; m_registered_sysvars= from->m_registered_sysvars; from->init(); } @@ -321,26 +64,20 @@ void Session_sysvars_tracker::vars_list::copy(vars_list* from, THD *thd) /** Inserts the variable to be tracked into m_registered_sysvars hash. - @param node Node to be inserted. @param svar address of the system variable @retval false success @retval true error */ -bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node, - const sys_var *svar, - myf mem_flag) +bool Session_sysvars_tracker::vars_list::insert(const sys_var *svar) { - if (!node) - { - if (!(node= (sysvar_node_st *) my_malloc(sizeof(sysvar_node_st), - MYF(MY_WME | mem_flag)))) - { - reinit(); - return true; - } - } + sysvar_node_st *node; + if (!(node= (sysvar_node_st *) my_malloc(sizeof(sysvar_node_st), + MYF(MY_WME | + (mysqld_server_initialized ? + MY_THREAD_SPECIFIC : 0))))) + return true; node->m_svar= (sys_var *)svar; node->test_load= node->m_svar->test_load; @@ -351,7 +88,6 @@ bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node, if (!search((sys_var *)svar)) { //EOF (error is already reported) - reinit(); return true; } } @@ -373,7 +109,6 @@ bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node, in case of invalid/duplicate values. @param char_set [IN] charecter set information used for string manipulations. - @param take_mutex [IN] take LOCK_plugin @return true Error @@ -382,44 +117,28 @@ bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node, bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd, LEX_STRING var_list, bool throw_error, - CHARSET_INFO *char_set, - bool take_mutex) + CHARSET_INFO *char_set) { const char separator= ','; char *token, *lasts= NULL; size_t rest= var_list.length; - reinit(); if (!var_list.str || var_list.length == 0) - { - buffer_length= 1; return false; - } - if(!strcmp(var_list.str,(const char *)"*")) + if(!strcmp(var_list.str, "*")) { track_all= true; - buffer_length= 2; return false; } - buffer_length= var_list.length + 1; token= var_list.str; track_all= false; - /* - If Lock to the plugin mutex is not acquired here itself, it results - in having to acquire it multiple times in find_sys_var_ex for each - token value. Hence the mutex is handled here to avoid a performance - overhead. - */ - if (!thd || take_mutex) - mysql_mutex_lock(&LOCK_plugin); for (;;) { sys_var *svar; - LEX_STRING var; - uint not_used; + LEX_CSTRING var; lasts= (char *) memchr(token, separator, rest); @@ -433,17 +152,16 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd, var.length= rest; /* Remove leading/trailing whitespace. */ - trim_whitespace(char_set, &var, ¬_used); + trim_whitespace(char_set, &var); - if(!strcmp(var.str,(const char *)"*")) + if(!strcmp(var.str, "*")) { track_all= true; } - else if ((svar= - find_sys_var_ex(thd, var.str, var.length, throw_error, true))) + else if ((svar= find_sys_var(thd, var.str, var.length, throw_error))) { - if (insert(NULL, svar, m_mem_flag) == TRUE) - goto error; + if (insert(svar) == TRUE) + return true; } else if (throw_error && thd) { @@ -453,55 +171,35 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd, "be ignored.", (int)var.length, token); } else - goto error; + return true; if (lasts) token= lasts + 1; else break; } - if (!thd || take_mutex) - mysql_mutex_unlock(&LOCK_plugin); - return false; - -error: - if (!thd || take_mutex) - mysql_mutex_unlock(&LOCK_plugin); - return true; } -bool Session_sysvars_tracker::check_var_list(THD *thd, - LEX_STRING var_list, - bool throw_error, - CHARSET_INFO *char_set, - bool take_mutex) +bool sysvartrack_validate_value(THD *thd, const char *str, size_t len) { + LEX_STRING var_list= { (char *) str, len }; const char separator= ','; char *token, *lasts= NULL; size_t rest= var_list.length; if (!var_list.str || var_list.length == 0 || - !strcmp(var_list.str,(const char *)"*")) + !strcmp(var_list.str, "*")) { return false; } token= var_list.str; - /* - If Lock to the plugin mutex is not acquired here itself, it results - in having to acquire it multiple times in find_sys_var_ex for each - token value. Hence the mutex is handled here to avoid a performance - overhead. - */ - if (!thd || take_mutex) - mysql_mutex_lock(&LOCK_plugin); for (;;) { - LEX_STRING var; - uint not_used; + LEX_CSTRING var; lasts= (char *) memchr(token, separator, rest); @@ -515,55 +213,19 @@ bool Session_sysvars_tracker::check_var_list(THD *thd, var.length= rest; /* Remove leading/trailing whitespace. */ - trim_whitespace(char_set, &var, ¬_used); + trim_whitespace(system_charset_info, &var); - if(!strcmp(var.str,(const char *)"*") && - !find_sys_var_ex(thd, var.str, var.length, throw_error, true)) - { - if (throw_error && take_mutex && thd) - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WRONG_VALUE_FOR_VAR, - "%.*s is not a valid system variable and will" - "be ignored.", (int)var.length, token); - } - else - { - if (!thd || take_mutex) - mysql_mutex_unlock(&LOCK_plugin); - return true; - } - } + if (!strcmp(var.str, "*") && !find_sys_var(thd, var.str, var.length)) + return true; if (lasts) token= lasts + 1; else break; } - if (!thd || take_mutex) - mysql_mutex_unlock(&LOCK_plugin); - return false; } -struct name_array_filler_data -{ - LEX_CSTRING **names; - uint idx; - -}; - -/** Collects variable references into array */ -my_bool Session_sysvars_tracker::name_array_filler(void *ptr, - void *data_ptr) -{ - Session_sysvars_tracker::sysvar_node_st *node= - (Session_sysvars_tracker::sysvar_node_st *)ptr; - name_array_filler_data *data= (struct name_array_filler_data *)data_ptr; - if (*node->test_load) - data->names[data->idx++]= &node->m_svar->name; - return FALSE; -} /* Sorts variable references array */ static int name_array_sorter(const void *a, const void *b) @@ -583,7 +245,8 @@ static int name_array_sorter(const void *a, const void *b) bool Session_sysvars_tracker::vars_list::construct_var_list(char *buf, size_t buf_len) { - struct name_array_filler_data data; + LEX_CSTRING **names; + uint idx; size_t left= buf_len; size_t names_size= m_registered_sysvars.records * sizeof(LEX_CSTRING *); const char separator= ','; @@ -606,16 +269,19 @@ bool Session_sysvars_tracker::vars_list::construct_var_list(char *buf, return false; } - data.names= (LEX_CSTRING**)my_safe_alloca(names_size); - - if (unlikely(!data.names)) + if (unlikely(!(names= (LEX_CSTRING**) my_safe_alloca(names_size)))) return true; - data.idx= 0; + idx= 0; mysql_mutex_lock(&LOCK_plugin); - my_hash_iterate(&m_registered_sysvars, &name_array_filler, &data); - DBUG_ASSERT(data.idx <= m_registered_sysvars.records); + for (ulong i= 0; i < m_registered_sysvars.records; i++) + { + sysvar_node_st *node= at(i); + if (*node->test_load) + names[idx++]= &node->m_svar->name; + } + DBUG_ASSERT(idx <= m_registered_sysvars.records); /* We check number of records again here because number of variables @@ -628,17 +294,16 @@ bool Session_sysvars_tracker::vars_list::construct_var_list(char *buf, return false; } - my_qsort(data.names, data.idx, sizeof(LEX_CSTRING *), - &name_array_sorter); + my_qsort(names, idx, sizeof(LEX_CSTRING*), &name_array_sorter); - for(uint i= 0; i < data.idx; i++) + for(uint i= 0; i < idx; i++) { - LEX_CSTRING *nm= data.names[i]; + LEX_CSTRING *nm= names[i]; size_t ln= nm->length + 1; if (ln > left) { mysql_mutex_unlock(&LOCK_plugin); - my_safe_afree(data.names, names_size); + my_safe_afree(names, names_size); return true; } memcpy(buf, nm->str, nm->length); @@ -649,58 +314,48 @@ bool Session_sysvars_tracker::vars_list::construct_var_list(char *buf, mysql_mutex_unlock(&LOCK_plugin); buf--; buf[0]= '\0'; - my_safe_afree(data.names, names_size); + my_safe_afree(names, names_size); return false; } -/** - Enable session tracker by parsing global value of tracked variables. - @param thd [IN] The thd handle. +void Session_sysvars_tracker::init(THD *thd) +{ + mysql_mutex_assert_owner(&LOCK_global_system_variables); + DBUG_ASSERT(thd->variables.session_track_system_variables == + global_system_variables.session_track_system_variables); + DBUG_ASSERT(global_system_variables.session_track_system_variables); + thd->variables.session_track_system_variables= + my_strdup(global_system_variables.session_track_system_variables, + MYF(MY_WME | MY_THREAD_SPECIFIC)); +} - @retval true Error - @retval false Success -*/ -bool Session_sysvars_tracker::enable(THD *thd) +void Session_sysvars_tracker::deinit(THD *thd) { - mysql_mutex_lock(&LOCK_plugin); - LEX_STRING tmp; - tmp.str= global_system_variables.session_track_system_variables; - tmp.length= safe_strlen(tmp.str); - if (tool_list->parse_var_list(thd, tmp, - true, thd->charset(), false) == true) - { - mysql_mutex_unlock(&LOCK_plugin); - return true; - } - mysql_mutex_unlock(&LOCK_plugin); - orig_list->copy(tool_list, thd); - m_enabled= true; - - return false; + my_free(thd->variables.session_track_system_variables); + thd->variables.session_track_system_variables= 0; } /** - Check system variable name(s). - - @note This function is called from the ON_CHECK() function of the - session_track_system_variables' sys_var class. + Enable session tracker by parsing global value of tracked variables. @param thd [IN] The thd handle. - @param var [IN] A pointer to set_var holding the specified list of - system variable names. @retval true Error @retval false Success */ -inline bool Session_sysvars_tracker::check_str(THD *thd, LEX_STRING *val) +bool Session_sysvars_tracker::enable(THD *thd) { - return Session_sysvars_tracker::check_var_list(thd, *val, true, - thd->charset(), true); + orig_list.reinit(); + m_parsed= false; + m_enabled= thd->variables.session_track_system_variables && + *thd->variables.session_track_system_variables; + reset_changed(); + return false; } @@ -710,6 +365,9 @@ inline bool Session_sysvars_tracker::check_str(THD *thd, LEX_STRING *val) Session_sysvars_tracker::vars_list::copy updating the hash in orig_list which represents the system variables to be tracked. + We are doing via tool list because there possible errors with memory + in this case value will be unchanged. + @note This function is called from the ON_UPDATE() function of the session_track_system_variables' sys_var class. @@ -721,37 +379,43 @@ inline bool Session_sysvars_tracker::check_str(THD *thd, LEX_STRING *val) bool Session_sysvars_tracker::update(THD *thd, set_var *var) { - /* - We are doing via tool list because there possible errors with memory - in this case value will be unchanged. - */ - tool_list->reinit(); - if (tool_list->parse_var_list(thd, var->save_result.string_value, true, - thd->charset(), true)) + vars_list tool_list; + void *copy= var->save_result.string_value.str ? + my_memdup(var->save_result.string_value.str, + var->save_result.string_value.length + 1, + MYF(MY_WME | MY_THREAD_SPECIFIC)) : + my_strdup("", MYF(MY_WME | MY_THREAD_SPECIFIC)); + + if (!copy) return true; - orig_list->copy(tool_list, thd); - return false; -} + if (tool_list.parse_var_list(thd, var->save_result.string_value, true, + thd->charset())) + { + my_free(copy); + return true; + } -/* - Function and structure to support storing variables from hash to the buffer. -*/ + my_free(thd->variables.session_track_system_variables); + thd->variables.session_track_system_variables= static_cast<char*>(copy); + + m_parsed= true; + orig_list.copy(&tool_list, thd); + orig_list.construct_var_list(thd->variables.session_track_system_variables, + var->save_result.string_value.length + 1); + return false; +} -struct st_store_variable_param -{ - THD *thd; - String *buf; -}; -my_bool Session_sysvars_tracker::store_variable(void *ptr, void *data_ptr) +bool Session_sysvars_tracker::vars_list::store(THD *thd, String *buf) { - Session_sysvars_tracker::sysvar_node_st *node= - (Session_sysvars_tracker::sysvar_node_st *)ptr; - if (node->m_changed) + for (ulong i= 0; i < m_registered_sysvars.records; i++) { - THD *thd= ((st_store_variable_param *)data_ptr)->thd; - String *buf= ((st_store_variable_param *)data_ptr)->buf; + sysvar_node_st *node= at(i); + + if (!node->m_changed) + continue; + char val_buf[SHOW_VAR_FUNC_BUFF_SIZE]; SHOW_VAR show; CHARSET_INFO *charset; @@ -760,7 +424,7 @@ my_bool Session_sysvars_tracker::store_variable(void *ptr, void *data_ptr) if (!*node->test_load) { mysql_mutex_unlock(&LOCK_plugin); - return false; + continue; } sys_var *svar= node->m_svar; bool is_plugin= svar->cast_pluginvar(); @@ -805,11 +469,6 @@ my_bool Session_sysvars_tracker::store_variable(void *ptr, void *data_ptr) return false; } -bool Session_sysvars_tracker::vars_list::store(THD *thd, String *buf) -{ - st_store_variable_param data= {thd, buf}; - return my_hash_iterate(&m_registered_sysvars, &store_variable, &data); -} /** Store the data for changed system variables in the specified buffer. @@ -825,13 +484,13 @@ bool Session_sysvars_tracker::vars_list::store(THD *thd, String *buf) bool Session_sysvars_tracker::store(THD *thd, String *buf) { - if (!orig_list->is_enabled()) + if (!orig_list.is_enabled()) return false; - if (orig_list->store(thd, buf)) + if (orig_list.store(thd, buf)) return true; - reset(); + orig_list.reset(); return false; } @@ -846,14 +505,27 @@ bool Session_sysvars_tracker::store(THD *thd, String *buf) void Session_sysvars_tracker::mark_as_changed(THD *thd, LEX_CSTRING *var) { - sysvar_node_st *node= NULL; + sysvar_node_st *node; sys_var *svar= (sys_var *)var; + + if (!m_parsed) + { + DBUG_ASSERT(thd->variables.session_track_system_variables); + LEX_STRING tmp= { thd->variables.session_track_system_variables, + strlen(thd->variables.session_track_system_variables) }; + if (orig_list.parse_var_list(thd, tmp, true, thd->charset())) + { + orig_list.reinit(); + return; + } + m_parsed= true; + } + /* Check if the specified system variable is being tracked, if so mark it as changed and also set the class's m_changed flag. */ - if (orig_list->is_enabled() && - (node= (sysvar_node_st *) (orig_list->insert_or_search(node, svar)))) + if (orig_list.is_enabled() && (node= orig_list.insert_or_search(svar))) { node->m_changed= true; State_tracker::mark_as_changed(thd, var); @@ -880,63 +552,41 @@ uchar *Session_sysvars_tracker::sysvars_get_key(const char *entry, } -/* Function to support resetting hash nodes for the variables */ - -my_bool Session_sysvars_tracker::reset_variable(void *ptr, - void *data_ptr) -{ - ((Session_sysvars_tracker::sysvar_node_st *)ptr)->m_changed= false; - return false; -} - void Session_sysvars_tracker::vars_list::reset() { - my_hash_iterate(&m_registered_sysvars, &reset_variable, NULL); + for (ulong i= 0; i < m_registered_sysvars.records; i++) + at(i)->m_changed= false; } -/** - Prepare/reset the m_registered_sysvars hash for next statement. -*/ -void Session_sysvars_tracker::reset() +bool sysvartrack_global_update(THD *thd, char *str, size_t len) { - - orig_list->reset(); - m_changed= false; + LEX_STRING tmp= { str, len }; + Session_sysvars_tracker::vars_list dummy; + if (!dummy.parse_var_list(thd, tmp, false, system_charset_info)) + { + dummy.construct_var_list(str, len + 1); + return false; + } + return true; } -static Session_sysvars_tracker* sysvar_tracker(THD *thd) -{ - return (Session_sysvars_tracker*) - thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER); -} -bool sysvartrack_validate_value(THD *thd, const char *str, size_t len) -{ - LEX_STRING tmp= {(char *)str, len}; - return Session_sysvars_tracker::server_init_check(thd, system_charset_info, - tmp); -} -bool sysvartrack_reprint_value(THD *thd, char *str, size_t len) -{ - LEX_STRING tmp= {str, len}; - return Session_sysvars_tracker::server_init_process(thd, - system_charset_info, - tmp); -} -bool sysvartrack_update(THD *thd, set_var *var) -{ - return sysvar_tracker(thd)->update(thd, var); -} -size_t sysvartrack_value_len(THD *thd) -{ - return sysvar_tracker(thd)->get_buffer_length(); -} -bool sysvartrack_value_construct(THD *thd, char *val, size_t len) +int session_tracker_init() { - return sysvar_tracker(thd)->construct_var_list(val, len); + DBUG_ASSERT(global_system_variables.session_track_system_variables); + if (sysvartrack_validate_value(0, + global_system_variables.session_track_system_variables, + strlen(global_system_variables.session_track_system_variables))) + { + sql_print_error("The variable session_track_system_variables has " + "invalid values."); + return 1; + } + return 0; } + /////////////////////////////////////////////////////////////////////////////// /** @@ -974,7 +624,7 @@ bool Current_schema_tracker::store(THD *thd, String *buf) It saves length of database name and name of database name + length of saved length of database length. */ - length= db_length= thd->db_length; + length= db_length= thd->db.length; length += net_length_size(length); compile_time_assert(SESSION_TRACK_SCHEMA < 251); @@ -991,39 +641,14 @@ bool Current_schema_tracker::store(THD *thd, String *buf) buf->q_net_store_length(length); /* Length and current schema name */ - buf->q_net_store_data((const uchar *)thd->db, thd->db_length); - - reset(); + buf->q_net_store_data((const uchar *)thd->db.str, thd->db.length); return false; } -/** - Reset the m_changed flag for next statement. - - @return void -*/ - -void Current_schema_tracker::reset() -{ - m_changed= false; -} - - /////////////////////////////////////////////////////////////////////////////// - -Transaction_state_tracker::Transaction_state_tracker() -{ - m_enabled = false; - tx_changed = TX_CHG_NONE; - tx_curr_state = - tx_reported_state= TX_EMPTY; - tx_read_flags = TX_READ_INHERIT; - tx_isol_level = TX_ISOL_INHERIT; -} - /** Enable/disable the tracker based on @@session_track_transaction_info. @@ -1185,7 +810,7 @@ bool Transaction_state_tracker::store(THD *thd, String *buf) statement even for a transaction that isn't the first in an ongoing chain. Consider - SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED; + SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT; # work COMMIT AND CHAIN; @@ -1193,7 +818,7 @@ bool Transaction_state_tracker::store(THD *thd, String *buf) If we switch away at this point, the replay in the new session needs to be - SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED; + SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION READ ONLY; When a transaction ends (COMMIT/ROLLBACK sans CHAIN), all @@ -1216,7 +841,7 @@ bool Transaction_state_tracker::store(THD *thd, String *buf) tx_isolation_typelib as it hyphenates its items. */ buf->append(STRING_WITH_LEN("SET TRANSACTION ISOLATION LEVEL ")); - buf->append(isol[tx_isol_level - 1].str, isol[tx_isol_level - 1].length); + buf->append(&isol[tx_isol_level - 1]); buf->append(STRING_WITH_LEN("; ")); } @@ -1333,25 +958,14 @@ bool Transaction_state_tracker::store(THD *thd, String *buf) } } - reset(); + tx_reported_state= tx_curr_state; + tx_changed= TX_CHG_NONE; return false; } /** - Reset the m_changed flag for next statement. -*/ - -void Transaction_state_tracker::reset() -{ - m_changed= false; - tx_reported_state= tx_curr_state; - tx_changed= TX_CHG_NONE; -} - - -/** Helper function: turn table info into table access flag. Accepts table lock type and engine type flag (transactional/ non-transactional), and returns the corresponding access flag @@ -1520,11 +1134,6 @@ void Transaction_state_tracker::set_isol_level(THD *thd, /////////////////////////////////////////////////////////////////////////////// -Session_state_change_tracker::Session_state_change_tracker() -{ - m_changed= false; -} - /** @Enable/disable the tracker based on @@session_track_state_change value. @@ -1562,106 +1171,15 @@ bool Session_state_change_tracker::store(THD *thd, String *buf) /* Length of the overall entity (1 byte) */ buf->q_append('\1'); - DBUG_ASSERT(is_state_changed(thd)); + DBUG_ASSERT(is_changed()); buf->q_append('1'); - reset(); - return false; } - -/** - Reset the m_changed flag for next statement. -*/ - -void Session_state_change_tracker::reset() -{ - m_changed= false; -} - - -/** - Find if there is a session state change. -*/ - -bool Session_state_change_tracker::is_state_changed(THD *) -{ - return m_changed; -} - /////////////////////////////////////////////////////////////////////////////// /** - @brief Initialize session tracker objects. -*/ - -Session_tracker::Session_tracker() -{ - /* track data ID fit into one byte in net coding */ - compile_time_assert(SESSION_TRACK_always_at_the_end < 251); - /* one tracker could serv several tracking data */ - compile_time_assert((uint)SESSION_TRACK_always_at_the_end >= - (uint)SESSION_TRACKER_END); - - for (int i= 0; i < SESSION_TRACKER_END; i++) - m_trackers[i]= NULL; -} - - -/** - @brief Enables the tracker objects. - - @param thd [IN] The thread handle. - - @return void -*/ - -void Session_tracker::enable(THD *thd) -{ - /* - Originally and correctly this allocation was in the constructor and - deallocation in the destructor, but in this case memory counting - system works incorrectly (for example in INSERT DELAYED thread) - */ - deinit(); - m_trackers[SESSION_SYSVARS_TRACKER]= - new (std::nothrow) Session_sysvars_tracker(); - m_trackers[CURRENT_SCHEMA_TRACKER]= - new (std::nothrow) Current_schema_tracker; - m_trackers[SESSION_STATE_CHANGE_TRACKER]= - new (std::nothrow) Session_state_change_tracker; - m_trackers[SESSION_GTIDS_TRACKER]= - new (std::nothrow) Not_implemented_tracker; - m_trackers[TRANSACTION_INFO_TRACKER]= - new (std::nothrow) Transaction_state_tracker; - - for (int i= 0; i < SESSION_TRACKER_END; i++) - m_trackers[i]->enable(thd); -} - - -/** - Method called during the server startup to verify the contents - of @@session_track_system_variables. - - @retval false Success - @retval true Failure -*/ - -bool Session_tracker::server_boot_verify(CHARSET_INFO *char_set) -{ - bool result; - LEX_STRING tmp; - tmp.str= global_system_variables.session_track_system_variables; - tmp.length= safe_strlen(tmp.str); - result= - Session_sysvars_tracker::server_init_check(NULL, char_set, tmp); - return result; -} - - -/** @brief Store all change information in the specified buffer. @param thd [IN] The thd handle. @@ -1673,6 +1191,12 @@ void Session_tracker::store(THD *thd, String *buf) { size_t start; + /* track data ID fit into one byte in net coding */ + compile_time_assert(SESSION_TRACK_always_at_the_end < 251); + /* one tracker could serv several tracking data */ + compile_time_assert((uint) SESSION_TRACK_always_at_the_end >= + (uint) SESSION_TRACKER_END); + /* Probably most track result will fit in 251 byte so lets made it at least efficient. We allocate 1 byte for length and then will move @@ -1684,11 +1208,15 @@ void Session_tracker::store(THD *thd, String *buf) /* Get total length. */ for (int i= 0; i < SESSION_TRACKER_END; i++) { - if (m_trackers[i]->is_changed() && - m_trackers[i]->store(thd, buf)) + if (m_trackers[i]->is_changed()) { - buf->length(start); // it is safer to have 0-length block in case of error - return; + if (m_trackers[i]->store(thd, buf)) + { + // it is safer to have 0-length block in case of error + buf->length(start); + return; + } + m_trackers[i]->reset_changed(); } } @@ -1717,5 +1245,3 @@ void Session_tracker::store(THD *thd, String *buf) net_store_length(data - 1, length); } - -#endif //EMBEDDED_LIBRARY |