diff options
author | unknown <jcole@tetra.spaceapes.com> | 2001-02-21 02:36:36 -0600 |
---|---|---|
committer | unknown <jcole@tetra.spaceapes.com> | 2001-02-21 02:36:36 -0600 |
commit | 1e5c62b059992fdaed344dd4669e7b851b0d53c8 (patch) | |
tree | d0e8b0625b11e6d922c94f718e69a07f8ee7af82 /sql | |
parent | 81c92d5a332097499d48109af91d84bc4f25b17a (diff) | |
parent | c749668eb7147356614f29ad9ce9e7781b23b0bc (diff) | |
download | mariadb-git-1e5c62b059992fdaed344dd4669e7b851b0d53c8.tar.gz |
Merge work.mysql.com:/home/bk/mysql
into tetra.spaceapes.com:/usr/home/jcole/bk/mysql
sql/mysqld.cc:
Auto merged
Diffstat (limited to 'sql')
30 files changed, 254 insertions, 68 deletions
diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 4b33c7b87ae..5116d6ef07f 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -172,9 +172,9 @@ convert_error_code_to_mysql( return(HA_ERR_TO_BIG_ROW); } else { - assert(0); + dbug_assert(0); - return(0); + return(-1); // Unknown error } } @@ -194,7 +194,7 @@ check_trx_exists( trx = (trx_t*) thd->transaction.all.innobase_tid; if (trx == NULL) { - assert(thd != NULL); + dbug_assert(thd != NULL); trx = trx_allocate_for_mysql(); thd->transaction.all.innobase_tid = trx; @@ -418,31 +418,41 @@ innobase_init(void) int err; bool ret; ibool test_bool; - + static char *current_dir[3]; DBUG_ENTER("innobase_init"); - test_bool = TRUE; - assert(test_bool == 1); - test_bool = FALSE; - assert(test_bool == 0); + /* Use current_dir if no paths are set */ + current_dir[0]=FN_CURLIB; + current_dir[1]=FN_LIBCHAR; + current_dir[2]=0; /* Set Innobase initialization parameters according to the values read from MySQL .cnf file */ - srv_data_home = innobase_data_home_dir; + if (!innobase_data_file_path) + { + fprintf(stderr,"Can't initialize innobase as 'innobase_data_file_path' is not set\n"); + DBUG_RETURN(TRUE); + } + + srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir : + current_dir); srv_logs_home = ""; - srv_arch_dir = innobase_log_arch_dir; + srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir : + current_dir); ret = innobase_parse_data_file_paths_and_sizes(); if (ret == FALSE) { - return(TRUE); + DBUG_RETURN(TRUE); } + if (!innobase_log_group_home_dir) + innobase_log_group_home_dir= current_dir; ret = innobase_parse_log_group_home_dirs(); if (ret == FALSE) { - return(TRUE); + DBUG_RETURN(TRUE); } srv_n_log_groups = (ulint) innobase_mirrored_log_groups; @@ -466,12 +476,12 @@ innobase_init(void) if (err != DB_SUCCESS) { - return(1); + DBUG_RETURN(1); } (void) hash_init(&innobase_open_tables,32,0,0, (hash_get_key) innobase_get_key,0,0); pthread_mutex_init(&innobase_mutex,NULL); - return(0); + DBUG_RETURN(0); } /*********************************************************************** @@ -490,10 +500,10 @@ innobase_end(void) if (err != DB_SUCCESS) { - return(1); + DBUG_RETURN(1); } - return(0); + DBUG_RETURN(0); } /******************************************************************** @@ -666,7 +676,7 @@ normalize_table_name( /* Scan name from the end */ - ptr = (char*) name + strlen(name) - 1; + ptr = strend(name)-1; while (ptr >= name && *ptr != '\\' && *ptr != '/') { ptr--; @@ -674,7 +684,7 @@ normalize_table_name( name_ptr = ptr + 1; - assert(ptr > name); + dbug_assert(ptr > name); ptr--; @@ -770,7 +780,7 @@ ha_innobase::open( ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = TRUE; - assert(key_used_on_scan == MAX_KEY); + dbug_assert(key_used_on_scan == MAX_KEY); } /* Init table lock structure */ @@ -911,8 +921,8 @@ innobase_mysql_cmp( { enum_field_types mysql_tp; - assert(a_length != UNIV_SQL_NULL); - assert(b_length != UNIV_SQL_NULL); + dbug_assert(a_length != UNIV_SQL_NULL); + dbug_assert(b_length != UNIV_SQL_NULL); mysql_tp = (enum_field_types) mysql_type; @@ -943,11 +953,11 @@ get_innobase_type_from_mysql_type( 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to the type */ - assert((ulint)FIELD_TYPE_STRING < 256); - assert((ulint)FIELD_TYPE_VAR_STRING < 256); - assert((ulint)FIELD_TYPE_DOUBLE < 256); - assert((ulint)FIELD_TYPE_FLOAT < 256); - assert((ulint)FIELD_TYPE_DECIMAL < 256); + dbug_assert((ulint)FIELD_TYPE_STRING < 256); + dbug_assert((ulint)FIELD_TYPE_VAR_STRING < 256); + dbug_assert((ulint)FIELD_TYPE_DOUBLE < 256); + dbug_assert((ulint)FIELD_TYPE_FLOAT < 256); + dbug_assert((ulint)FIELD_TYPE_DECIMAL < 256); switch (field->type()) { case FIELD_TYPE_VAR_STRING: if (field->flags & BINARY_FLAG) { @@ -1072,6 +1082,14 @@ build_template( templ_type = ROW_MYSQL_WHOLE_ROW; } + if (prebuilt->select_lock_type == LOCK_X) { + /* TODO: should fix the code in sql_update so that we could do + with fetching only the needed columns */ + + templ_type = ROW_MYSQL_WHOLE_ROW; + } + + if (templ_type == ROW_MYSQL_REC_FIELDS) { if (prebuilt->select_lock_type != LOCK_NONE) { @@ -1288,9 +1306,9 @@ calc_row_difference( uint n_fields; ulint o_len; ulint n_len; - mysql_byte* o_ptr; - mysql_byte* n_ptr; - mysql_byte* buf; + byte* o_ptr; + byte* n_ptr; + byte* buf; upd_field_t* ufield; ulint col_type; ulint is_unsigned; @@ -1300,7 +1318,7 @@ calc_row_difference( n_fields = table->fields; /* We use upd_buff to convert changed fields */ - buf = upd_buff; + buf = (byte*) upd_buff; for (i = 0; i < n_fields; i++) { field = table->field[i]; @@ -1312,8 +1330,8 @@ calc_row_difference( goto skip_field; } - o_ptr = old_row + get_field_offset(table, field); - n_ptr = new_row + get_field_offset(table, field); + o_ptr = (byte*) old_row + get_field_offset(table, field); + n_ptr = (byte*) new_row + get_field_offset(table, field); o_len = field->pack_length(); n_len = field->pack_length(); @@ -1353,8 +1371,10 @@ calc_row_difference( ufield = uvect->fields + n_changed; - buf = innobase_convert_and_store_changed_col(ufield, - buf, n_ptr, n_len, col_type, + buf = (byte*) + innobase_convert_and_store_changed_col(ufield, + (mysql_byte*)buf, + (mysql_byte*)n_ptr, n_len, col_type, is_unsigned); ufield->exp = NULL; ufield->field_no = @@ -1580,7 +1600,7 @@ ha_innobase::index_read( last_match_mode = match_mode; - ret = row_search_for_mysql(buf, mode, prebuilt, match_mode, 0); + ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0); if (ret == DB_SUCCESS) { error = 0; @@ -1690,7 +1710,8 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); - ret = row_search_for_mysql(buf, 0, prebuilt, match_mode, direction); + ret = row_search_for_mysql((byte*)buf, 0, prebuilt, + match_mode, direction); if (ret == DB_SUCCESS) { error = 0; @@ -1935,7 +1956,7 @@ ha_innobase::position( len = store_key_val_for_row(primary_key, (char*) ref, record); } - assert(len <= ref_length); + dbug_assert(len <= ref_length); ref_stored_len = len; } @@ -2174,23 +2195,14 @@ ha_innobase::create( int primary_key_no = -1; KEY* key; uint i; - char name2[1000]; - char norm_name[1000]; + char name2[FN_REFLEN]; + char norm_name[FN_REFLEN]; DBUG_ENTER("ha_innobase::create"); trx = trx_allocate_for_mysql(); - name_len = strlen(name); - - assert(name_len < 1000); - assert(name_len > 4); - - memcpy(name2, name, name_len); - - /* Erase the .frm end from table name: */ - - name2[name_len - 4] = '\0'; + fn_format(name2, name, "", "",2); // Remove the .frm extension normalize_table_name(norm_name, name2); @@ -2550,11 +2562,11 @@ ha_innobase::update_table_comment( char *str=my_malloc(length + 50,MYF(0)); if (!str) - return comment; + return (char*)comment; sprintf(str,"%s Innobase free: %lu kB", comment,innobase_get_free_space()); - return str; + return((char*) str); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 38f353d4ec7..d643952c5b0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -85,10 +85,11 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO; } data_len = uint4korr(buf + EVENT_LEN_OFFSET); - if (data_len < LOG_EVENT_HEADER_LEN || data_len > MAX_EVENT_LEN) + if (data_len < LOG_EVENT_HEADER_LEN || data_len > max_allowed_packet) { if (log_lock) pthread_mutex_unlock(log_lock); - return LOG_READ_BOGUS; + return (data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS : + LOG_READ_TOO_LARGE; } packet->append(buf, sizeof(buf)); data_len -= LOG_EVENT_HEADER_LEN; diff --git a/sql/log_event.h b/sql/log_event.h index 8a22048bba4..79186e329da 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -31,6 +31,7 @@ #define LOG_READ_IO -3 #define LOG_READ_MEM -5 #define LOG_READ_TRUNC -6 +#define LOG_READ_TOO_LARGE -7 #define LOG_EVENT_OFFSET 4 #define BINLOG_VERSION 1 @@ -42,7 +43,6 @@ + sizeof(uint32) + 2 + sizeof(uint32)) #define EVENT_LEN_OFFSET 9 #define EVENT_TYPE_OFFSET 4 -#define MAX_EVENT_LEN 4*1024*1024 #define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN) #define ROTATE_EVENT_OVERHEAD LOG_EVENT_HEADER_LEN #define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN+sizeof(sql_ex_info)) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4e324704a31..352cdcee6f6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -231,6 +231,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_change_db(THD *thd,const char *name); void mysql_parse(THD *thd,char *inBuf,uint length); void mysql_init_select(LEX *lex); +void init_max_user_conn(void); +void free_max_user_conn(void); pthread_handler_decl(handle_one_connection,arg); pthread_handler_decl(handle_bootstrap,arg); sig_handler end_thread_signal(int sig); @@ -519,7 +521,7 @@ extern uint protocol_version,dropping_tables; extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size, max_join_size,join_buff_size,tmp_table_size, max_connections,max_connect_errors,long_query_time, - max_insert_delayed_threads, + max_insert_delayed_threads, max_user_connections, long_query_count,net_wait_timeout,net_interactive_timeout, net_read_timeout,net_write_timeout, what_to_log,flush_time, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7cadc710ee1..a34cebcc9dd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -263,7 +263,7 @@ ulong select_full_range_join_count,select_full_join_count; ulong specialflag=0,opened_tables=0,created_tmp_tables=0, created_tmp_disk_tables=0; ulong max_connections,max_insert_delayed_threads,max_used_connections, - max_connect_errors; + max_connect_errors, max_user_connections = 0; ulong thread_id=1L,current_pid; ulong slow_launch_threads = 0; char mysql_real_data_home[FN_REFLEN], @@ -295,7 +295,8 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count, LOCK_error_log, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received, - LOCK_binlog_update, LOCK_slave, LOCK_server_id; + LOCK_binlog_update, LOCK_slave, LOCK_server_id, + LOCK_user_conn; pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update, COND_slave_stopped, COND_slave_start; @@ -647,6 +648,7 @@ void clean_up(void) my_free(mysql_tmpdir,MYF(0)); x_free(opt_bin_logname); bitmap_free(&temp_pool); + free_max_user_conn(); #ifndef __WIN__ if (!opt_bootstrap) (void) my_delete(pidfile_name,MYF(0)); // This may not always exist @@ -1576,6 +1578,7 @@ int main(int argc, char **argv) (void) pthread_mutex_init(&LOCK_binlog_update, NULL); (void) pthread_mutex_init(&LOCK_slave, NULL); (void) pthread_mutex_init(&LOCK_server_id, NULL); + (void) pthread_mutex_init(&LOCK_user_conn, NULL); (void) pthread_cond_init(&COND_binlog_update, NULL); (void) pthread_cond_init(&COND_slave_stopped, NULL); (void) pthread_cond_init(&COND_slave_start, NULL); @@ -1766,6 +1769,8 @@ The server will not act as a slave."); } if (!opt_noacl) (void) grant_init(); + if (max_user_connections) + init_max_user_conn(); #ifdef HAVE_DLOPEN if (!opt_noacl) @@ -2631,6 +2636,8 @@ CHANGEABLE_VAR changeable_vars[] = { 1024, 4, 8192*1024L, 0, 1 }, { "max_tmp_tables", (long*) &max_tmp_tables, 32, 1, ~0L, 0, 1 }, + { "max_user_connections", (long*) &max_user_connections, + 0, 1, ~0L, 0, 1 }, { "max_write_lock_count", (long*) &max_write_lock_count, ~0L, 1, ~0L, 0, 1 }, { "myisam_sort_buffer_size", (long*) &myisam_sort_buffer_size, @@ -2726,6 +2733,7 @@ struct show_var_st init_vars[]= { {"max_heap_table_size", (char*) &max_heap_table_size, SHOW_LONG}, {"max_join_size", (char*) &max_join_size, SHOW_LONG}, {"max_sort_length", (char*) &max_item_sort_length, SHOW_LONG}, + {"max_user_connections", (char*) &max_user_connections, SHOW_LONG}, {"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG}, {"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, @@ -3849,6 +3857,10 @@ static int get_service_parameters() { SET_CHANGEABLE_VARVAL( "max_connections" ); } + else if ( lstrcmp(szKeyValueName, TEXT("MaxUserConnections")) == 0 ) + { + SET_CHANGEABLE_VARVAL( "max_user_connections" ); + } else if ( lstrcmp(szKeyValueName, TEXT("MaxConnectErrors")) == 0 ) { SET_CHANGEABLE_VARVAL( "max_connect_errors" ); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 319d8a88149..0ba76ca4ff2 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -213,3 +213,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 43aad2f71e4..eb2a5dc3dd2 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -207,3 +207,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 74bc2fe992d..3ef00cf0837 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 941e7f434ea..5148b25e4cf 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 227b6336562..f42b5209ea6 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -208,3 +208,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 594da49c32e..949a12a52b3 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 621cef7affa..89401557f6c 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -207,3 +207,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index dfaea718fb1..f9018013875 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index a6388ed624e..c81466104a7 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -206,3 +206,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index f182608798e..25dd252797e 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 04b411239ae..008303c3cf5 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -206,3 +206,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index e1efb0c15ae..231d00b44b2 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 5484b58425e..50a3345351d 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -206,3 +206,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 4db4af5457f..b31429fca0d 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -206,3 +206,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 5e90cf05b8e..d8126917c1b 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -208,3 +208,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 33618a0e671..c1f4595f1b2 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -204,3 +204,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 115bcc299f2..235493e538d 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -208,3 +208,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index d3564e5ef5b..c08c471e9e1 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -207,3 +207,4 @@ "üÔÏÔ ÓÅÒ×ÅÒ ÎÅ slave, ÉÓÐÒÁ×ØÔÅ × ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÍ ÆÁÊÌÅ ÉÌÉ ËÏÍÍÁÎÄÏÊ CHANGE MASTER TO", "îÅ ÐÏÌÕÞÉÌÏÓØ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ÓÔÒÕËÔÕÒÕ master info, ÐÒÏ×ÅÒÔÅ persmissions ÎÁ ÆÁÊÌÅ master.info", "îÅ ÍÏÇÕ ÓÏÚÄÁÔØ ÐÒÏÃÅÓÓ SLAVE, ÐÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 82817fff7d6..c80e30bb775 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -212,3 +212,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 50c5f4ea8c1..641ac3e1dce 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -205,3 +205,4 @@ "The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "Could not initialize master info structure, check permisions on master.info", "Could not create slave thread, check system resources", +"User %-.64s has already more than 'max_user_connections' active connections", diff --git a/sql/share/swedish/errmsg.OLD b/sql/share/swedish/errmsg.OLD index ee3d913e51a..132a9fdf4f9 100644 --- a/sql/share/swedish/errmsg.OLD +++ b/sql/share/swedish/errmsg.OLD @@ -199,3 +199,9 @@ "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", +"Denna operation kan inte göras under replikering; Gör SLAVE STOP först", +"Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START", +"Servern är inte konfigurerade som en replikations slav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO", +"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'", +"Kunde inte starta en tråd för replikering", +"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index a47bdf7428e..132a9fdf4f9 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -199,8 +199,9 @@ "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Utöka denna mysqld variabel och försök på nytt", -"This operation cannot be performed with a running slave, run SLAVE STOP first", -"This operation requires a running slave, configure slave and do SLAVE START", -"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", -"Could not initialize master info structure, check permisions on master.info", -"Could not create slave thread, check system resources", +"Denna operation kan inte göras under replikering; Gör SLAVE STOP först", +"Denna operation kan endast göras under replikering; Konfigurera slaven och gör SLAVE START", +"Servern är inte konfigurerade som en replikations slav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO", +"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'", +"Kunde inte starta en tråd för replikering", +"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar", diff --git a/sql/sql_class.h b/sql/sql_class.h index cc5095397b6..f9720a3774a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -265,14 +265,14 @@ public: pthread_t real_id; uint current_tablenr,tmp_table,cond_count,col_access,query_length; uint server_status,open_options; - bool slave_thread; char scramble[9]; + bool slave_thread; bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool no_errors, allow_sum_func, password, fatal_error; bool query_start_used,last_insert_id_used,insert_id_used; - bool volatile killed,bootstrap; bool system_thread,in_lock_tables,global_read_lock; - bool query_error; + bool query_error, bootstrap; + bool volatile killed; LOG_INFO* current_linfo; // if we do a purge of binary logs, log index info of the threads // that are currently reading it needs to be adjusted. To do that diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ebf49583e7b..5ff0bc91c5f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -22,6 +22,7 @@ #include <thr_alarm.h> #include <myisam.h> #include <my_dir.h> +#include <assert.h> #define SCRAMBLE_LENGTH 8 @@ -32,6 +33,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache; extern "C" int gethostname(char *name, int namelen); #endif +static int check_for_max_user_connections(const char *user, int u_length, + const char *host); +static void decrease_user_connections(const char *user, const char *host); static bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); @@ -145,13 +149,134 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip", db ? db : (char*) ""); thd->db_access=0; + if (max_user_connections && + check_for_max_user_connections(user, strlen(user), thd->host)) + return -1; if (db && db[0]) - return test(mysql_change_db(thd,db)); + { + bool error=test(mysql_change_db(thd,db)); + if (error) + decrease_user_connections(user,thd->host); + return error; + } else send_ok(net); // Ready to handle questions return 0; // ok } +/* +** check for maximum allowable user connections +** if mysql server is started with corresponding +** variable that is greater then 0 +*/ + +static HASH hash_user_connections; +static DYNAMIC_ARRAY user_conn_array; +extern pthread_mutex_t LOCK_user_conn; + +struct user_conn { + char user[USERNAME_LENGTH+HOSTNAME_LENGTH+2]; + int connections, len; +}; + +static byte* get_key_conn(user_conn *buff, uint *length, + my_bool not_used __attribute__((unused))) +{ + *length=buff->len; + return (byte*) buff->user; +} + +#define DEF_USER_COUNT 50 + +void init_max_user_conn(void) +{ + (void) hash_init(&hash_user_connections,DEF_USER_COUNT,0,0, + (hash_get_key) get_key_conn,0, 0); + (void) init_dynamic_array(&user_conn_array,sizeof(user_conn), + DEF_USER_COUNT, DEF_USER_COUNT); +} + + +static int check_for_max_user_connections(const char *user, int u_length, + const char *host) +{ + uint temp_len; + char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2]; + struct user_conn *uc; + if (!user) + user=""; + if (!host) + host=""; + temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host, + NullS) - temp_user); + (void) pthread_mutex_lock(&LOCK_user_conn); + uc = (struct user_conn *) hash_search(&hash_user_connections, + (byte*) temp_user, temp_len); + if (uc) /* user found ; check for no. of connections */ + { + if (max_user_connections == uc->connections) + { + net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, temp_user); + pthread_mutex_unlock(&LOCK_user_conn); + return 1; + } + uc->connections++; + } + else + { + /* the user is not found in the cache; Insert it */ + struct user_conn uc; + memcpy(uc.user,temp_user,temp_len+1); + uc.len = temp_len; + uc.connections = 1; + if (!insert_dynamic(&user_conn_array, (char *) &uc)) + { + hash_insert(&hash_user_connections, + (byte *) dynamic_array_ptr(&user_conn_array, + user_conn_array.elements - 1)); + } + } + (void) pthread_mutex_unlock(&LOCK_user_conn); + return 0; +} + + +static void decrease_user_connections(const char *user, const char *host) +{ + char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2]; + int temp_len; + struct user_conn uucc, *uc; + if (!user) + user=""; + if (!host) + host=""; + temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host, + NullS) - temp_user); + (void) pthread_mutex_lock(&LOCK_user_conn); + + uc = (struct user_conn *) hash_search(&hash_user_connections, + (byte*) temp_user, temp_len); + dbug_assert(uc != 0); // We should always find the user + if (!uc) + goto end; // Safety; Something went wrong + if (! --uc->connections) + { + /* Last connection for user; Delete it */ + (void) hash_delete(&hash_user_connections,(char *) uc); + uint element= ((uint) ((byte*) uc - (byte*) user_conn_array.buffer) / + user_conn_array.size_of_element); + delete_dynamic_element(&user_conn_array,element); + } +end: + (void) pthread_mutex_unlock(&LOCK_user_conn); +} + +void free_max_user_conn(void) +{ + delete_dynamic(&user_conn_array); + hash_free(&hash_user_connections); +} + /* ** check connnetion and get priviliges @@ -417,6 +542,8 @@ pthread_handler_decl(handle_one_connection,arg) thread_safe_increment(aborted_threads,&LOCK_thread_count); } + if (max_user_connections) + decrease_user_connections(thd->user,thd->host); end_thread: close_connection(net); end_thread(thd,1); @@ -512,7 +639,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) DBUG_ENTER("mysql_table_dump"); db = (db && db[0]) ? db : thd->db; if (!(table_list = (TABLE_LIST*) sql_calloc(sizeof(TABLE_LIST)))) - DBUG_RETURN(1); // out of memory + DBUG_RETURN(1); // out of memory table_list->db = db; table_list->real_name = table_list->name = tbl_name; table_list->lock_type = TL_READ_NO_INSERT; @@ -641,7 +768,7 @@ bool do_command(THD *thd) send_error(net, ER_UNKNOWN_COM_ERROR); break; } - if (check_user(thd, COM_CHANGE_USER, user, passwd, db,0)) + if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0)) { // Restore old user x_free(thd->user); x_free(thd->db); @@ -652,6 +779,7 @@ bool do_command(THD *thd) thd->priv_user=save_priv_user; break; } + decrease_user_connections (save_user, thd->host); x_free((gptr) save_db); x_free((gptr) save_user); thd->password=test(passwd[0]); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 7730706f0d0..e354bb65713 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -352,6 +352,10 @@ sweepstakes if you report the bug"; case LOG_READ_BOGUS: errmsg = "bogus data in log event"; break; + case LOG_READ_TOO_LARGE: + errmsg = "log event entry exceeded max_allowed_packet -\ + increase max_allowed_packet on master"; + break; case LOG_READ_IO: errmsg = "I/O error reading log event"; break; |