diff options
author | unknown <monty@narttu.mysql.fi> | 2003-06-04 19:21:51 +0300 |
---|---|---|
committer | unknown <monty@narttu.mysql.fi> | 2003-06-04 19:21:51 +0300 |
commit | 13f7e49494559bba3195ccf3abdb349fbe79b6dc (patch) | |
tree | 6b8e47374bf313429416a26678bc409946f34772 /sql | |
parent | b388eb004df7112b2ae0986457fc9d01131b71ea (diff) | |
parent | b5860aed7b1d11f2d3ac909cde1438c86af26cb5 (diff) | |
download | mariadb-git-13f7e49494559bba3195ccf3abdb349fbe79b6dc.tar.gz |
Merge with 4.0.13
BitKeeper/etc/logging_ok:
auto-union
BUILD/SETUP.sh:
Auto merged
BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43:
Auto merged
client/mysqltest.c:
Auto merged
include/config-win.h:
Auto merged
include/my_global.h:
Auto merged
include/mysql_com.h:
Auto merged
innobase/include/srv0srv.h:
Auto merged
innobase/log/log0log.c:
Auto merged
innobase/os/os0file.c:
Auto merged
innobase/srv/srv0srv.c:
Auto merged
innobase/srv/srv0start.c:
Auto merged
innobase/ut/ut0mem.c:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/r/alter_table.result:
Auto merged
mysql-test/r/errors.result:
Auto merged
mysql-test/r/loaddata.result:
Auto merged
mysql-test/r/rpl_insert_id.result:
Auto merged
mysql-test/r/rpl_loaddata.result:
Auto merged
mysql-test/std_data/rpl_loaddata2.dat:
Auto merged
mysql-test/t/alter_table.test:
Auto merged
mysql-test/t/loaddata.test:
Auto merged
mysql-test/t/query_cache.test:
Auto merged
mysql-test/t/raid.test:
Auto merged
mysql-test/t/rpl_insert_id.test:
Auto merged
mysql-test/t/rpl_loaddata.test:
Auto merged
sql/field.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/time.cc:
Auto merged
configure.in:
No changes
libmysqld/lib_sql.cc:
No changes
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 3 | ||||
-rw-r--r-- | sql/log.cc | 51 | ||||
-rw-r--r-- | sql/mysql_priv.h | 4 | ||||
-rw-r--r-- | sql/mysqld.cc | 52 | ||||
-rw-r--r-- | sql/set_var.cc | 2 | ||||
-rw-r--r-- | sql/slave.cc | 27 | ||||
-rw-r--r-- | sql/sql_cache.cc | 16 | ||||
-rw-r--r-- | sql/sql_insert.cc | 24 | ||||
-rw-r--r-- | sql/sql_table.cc | 133 | ||||
-rw-r--r-- | sql/sql_update.cc | 1 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 3 | ||||
-rw-r--r-- | sql/time.cc | 56 |
12 files changed, 244 insertions, 128 deletions
diff --git a/sql/field.cc b/sql/field.cc index a61654ed8f4..f610f95ae0e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2755,6 +2755,7 @@ int Field_timestamp::store(longlong nr) if ((nr=fix_datetime(nr))) { + long not_used; part1=(long) (nr/LL(1000000)); part2=(long) (nr - (longlong) part1*LL(1000000)); l_time.year= (int) (part1/10000L); part1%=10000L; @@ -2763,7 +2764,7 @@ int Field_timestamp::store(longlong nr) l_time.hour= (int) (part2/10000L); part2%=10000L; l_time.minute=(int) part2 / 100; l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time); + timestamp=my_gmt_sec(&l_time, ¬_used); } else timestamp=0; diff --git a/sql/log.cc b/sql/log.cc index c05d52bdc5d..0ccb40c5246 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1200,6 +1200,12 @@ bool MYSQL_LOG::write(Log_event* event_info) No check for auto events flag here - this write method should never be called if auto-events are enabled */ + + /* + 1. Write first log events which describe the 'run environment' + of the SQL command + */ + if (thd) { if (thd->last_insert_id_used) @@ -1245,7 +1251,7 @@ bool MYSQL_LOG::write(Log_event* event_info) goto err; } } -#if 0 +#ifdef TO_BE_REMOVED if (thd->variables.convert_set) { char buf[256], *p; @@ -1257,12 +1263,39 @@ bool MYSQL_LOG::write(Log_event* event_info) goto err; } #endif + + /* + If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL + command in the binlog inside: + SET FOREIGN_KEY_CHECKS=0; + <command>; + SET FOREIGN_KEY_CHECKS=1; + */ + + if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } } + + /* Write the SQL command */ + event_info->set_log_pos(this); - if (event_info->write(file) || - file == &log_file && flush_io_cache(file)) + if (event_info->write(file)) goto err; - error=0; + + /* Write log events to reset the 'run environment' of the SQL command */ + + if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } /* Tell for transactional table handlers up to which position in the @@ -1283,6 +1316,9 @@ bool MYSQL_LOG::write(Log_event* event_info) if (file == &log_file) // we are writing to the real log (disk) { + if (flush_io_cache(file)) + goto err; + if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log)) { /* @@ -1292,8 +1328,8 @@ bool MYSQL_LOG::write(Log_event* event_info) handler if the log event type is appropriate. */ - if (event_info->get_type_code() == QUERY_EVENT - || event_info->get_type_code() == EXEC_LOAD_EVENT) + if (event_info->get_type_code() == QUERY_EVENT || + event_info->get_type_code() == EXEC_LOAD_EVENT) { error = ha_report_binlog_offset_and_commit(thd, log_file_name, file->pos_in_file); @@ -1303,6 +1339,7 @@ bool MYSQL_LOG::write(Log_event* event_info) /* we wrote to the real log, check automatic rotation */ should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size); } + error=0; err: if (error) @@ -1329,7 +1366,7 @@ err: Flush the transactional handler log file now that we have released LOCK_log; the flush is placed here to eliminate the bottleneck on the group commit - */ + */ if (called_handler_commit) ha_commit_complete(thd); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 97158191111..b7e8c0bd0ab 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -461,7 +461,6 @@ bool mysql_rename_table(enum db_type base, const char * old_name, const char *new_db, const char * new_name); -bool close_cached_table(THD *thd,TABLE *table); int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys); int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop_list); @@ -501,6 +500,7 @@ Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, bool check_grant,bool allow_rowid); #ifdef HAVE_OPENSSL +#include <openssl/des.h> struct st_des_keyblock { des_cblock key1, key2, key3; @@ -837,7 +837,7 @@ uint calc_days_in_year(uint year); void get_date_from_daynr(long daynr,uint *year, uint *month, uint *day); void init_time(void); -long my_gmt_sec(TIME *); +long my_gmt_sec(TIME *, long *current_timezone); time_t str_to_timestamp(const char *str,uint length); bool str_to_time(const char *str,uint length,TIME *l_time); longlong str_to_datetime(const char *str,uint length,bool fuzzy_date); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 019a3388341..c6922edb674 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -566,7 +566,7 @@ static void close_connections(void) unix_sock= INVALID_SOCKET; } #endif - end_thr_alarm(); // Don't allow alarms + end_thr_alarm(0); // Abort old alarms. end_slave(); /* First signal all threads that it's time to die */ @@ -875,6 +875,7 @@ void clean_up(bool print_message) #endif (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ end_key_cache(); + end_thr_alarm(1); /* Free allocated memory */ #ifdef USE_RAID end_raid(); #endif @@ -940,7 +941,6 @@ static void clean_up_mutexes() (void) pthread_mutex_destroy(&LOCK_crypt); (void) pthread_mutex_destroy(&LOCK_bytes_sent); (void) pthread_mutex_destroy(&LOCK_bytes_received); - (void) pthread_mutex_destroy(&LOCK_timezone); (void) pthread_mutex_destroy(&LOCK_user_conn); #ifdef HAVE_REPLICATION (void) pthread_mutex_destroy(&LOCK_rpl_status); @@ -1501,7 +1501,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\ and this may fail.\n\n"); fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size); fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size); - fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size); fprintf(stderr, "max_used_connections=%ld\n", max_used_connections); fprintf(stderr, "max_connections=%ld\n", max_connections); fprintf(stderr, "threads_connected=%d\n", thread_count); @@ -1509,7 +1508,7 @@ and this may fail.\n\n"); key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\ bytes of memory\n", ((ulong) keybuff_size + (global_system_variables.read_buff_size + - thd->variables.sortbuff_size) * + global_system_variables.sortbuff_size) * max_connections)/ 1024); fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n"); @@ -1538,14 +1537,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n", Some pointers may be invalid and cause the dump to abort...\n"); safe_print_str("thd->query", thd->query, 1024); fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id); - fprintf(stderr, "\n\ -Successfully dumped variables, if you ran with --log, take a look at the\n\ -details of what thread %ld did to cause the crash. In some cases of really\n\ -bad corruption, the values shown above may be invalid.\n\n", - thd->thread_id); } fprintf(stderr, "\ -The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\ +The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\ information that should help you find out what is causing the crash.\n"); fflush(stderr); #endif /* HAVE_STACKTRACE */ @@ -1569,6 +1563,7 @@ information that should help you find out what is causing the crash.\n"); static void init_signals(void) { sigset_t set; + struct sigaction sa; DBUG_ENTER("init_signals"); sigset(THR_KILL_SIGNAL,end_thread_signal); @@ -1576,7 +1571,6 @@ static void init_signals(void) if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) { - struct sigaction sa; sa.sa_flags = SA_RESETHAND | SA_NODEFER; sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); @@ -1618,15 +1612,23 @@ static void init_signals(void) sigaddset(&set,SIGQUIT); sigaddset(&set,SIGTERM); sigaddset(&set,SIGHUP); - sigset(SIGTERM, print_signal_warning); // If it's blocked by parent - sigset(SIGHUP, print_signal_warning); // If it's blocked by parent + + /* Fix signals if blocked by parents (can happen on Mac OS X) */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = print_signal_warning; + sigaction(SIGTERM, &sa, (struct sigaction*) 0); + sa.sa_flags = 0; + sa.sa_handler = print_signal_warning; + sigaction(SIGHUP, &sa, (struct sigaction*) 0); #ifdef SIGTSTP sigaddset(&set,SIGTSTP); #endif sigaddset(&set,THR_SERVER_ALARM); sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT sigdelset(&set,THR_CLIENT_ALARM); // For alarms - (void) pthread_sigmask(SIG_SETMASK,&set,NULL); + sigprocmask(SIG_SETMASK,&set,NULL); + pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; } @@ -1894,7 +1896,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg) #endif -const char *load_default_groups[]= { "mysqld","server",0 }; +const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 }; bool open_log(MYSQL_LOG *log, const char *hostname, const char *opt_name, const char *extension, @@ -1951,19 +1953,11 @@ static int init_common_variables(const char *conf_file_name, int argc, } #endif #ifdef HAVE_TZNAME -#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) { struct tm tm_tmp; localtime_r(&start_time,&tm_tmp); strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]); } -#else - { - struct tm *start_tm; - start_tm=localtime(&start_time); - strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]); - } -#endif #endif if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) @@ -2075,7 +2069,6 @@ static int init_thread_environment() (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST); @@ -2441,14 +2434,14 @@ The server will not act as a slave."); if (opt_bootstrap) { int error=bootstrap(stdin); - end_thr_alarm(); // Don't allow alarms + end_thr_alarm(1); // Don't allow alarms unireg_abort(error ? 1 : 0); } if (opt_init_file) { if (read_init_file(opt_init_file)) { - end_thr_alarm(); // Don't allow alarms + end_thr_alarm(1); // Don't allow alarms unireg_abort(1); } } @@ -2620,9 +2613,12 @@ int main(int argc, char **argv) return 0; if (Service.IsService(argv[2])) { - /* start an optional service */ + /* + mysqld was started as + mysqld --defaults-file=my_path\my.ini service-name + */ use_opt_args=1; - opt_argc=argc; + opt_argc= 2; // Skip service-name opt_argv=argv; start_mode= 1; Service.Init(argv[2], mysql_service); diff --git a/sql/set_var.cc b/sql/set_var.cc index 42ea92825d1..b772f6410f7 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -209,6 +209,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count", sys_var_thd_bool sys_new_mode("new", &SV::new_mode); sys_var_thd_ulong sys_read_buff_size("read_buffer_size", &SV::read_buff_size); +sys_var_bool_ptr sys_readonly("read_only", &opt_readonly); sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", &SV::read_rnd_buff_size); #ifdef HAVE_REPLICATION @@ -596,6 +597,7 @@ struct show_var_st init_vars[]= { {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, + {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, #ifdef HAVE_REPLICATION {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, diff --git a/sql/slave.cc b/sql/slave.cc index be95cc16d90..21674d9ece2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1388,9 +1388,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) while (rli->log_space_limit < rli->log_space_total && !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) - { pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); - } thd->proc_info = save_proc_info; pthread_mutex_unlock(&rli->log_space_lock); DBUG_RETURN(slave_killed); @@ -2101,7 +2099,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) Log_event * ev = next_event(rli); DBUG_ASSERT(rli->sql_thd==thd); if (sql_slave_killed(thd,rli)) + { + /* do not forget to free ev ! */ + if (ev) delete ev; return 1; + } if (ev) { int type_code = ev->get_type_code(); @@ -2376,6 +2378,18 @@ reconnect done to recover from failed read"); goto err; } flush_master_info(mi); + /* + See if the relay logs take too much space. + We don't lock mi->rli.log_space_lock here; this dirty read saves time + and does not introduce any problem: + - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so + the clean value is 0), then we are reading only one more event as we + should, and we'll block only at the next event. No big deal. + - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so + the clean value is 1), then we are going into wait_for_relay_log_space() + for no reason, but this function will do a clean read, notice the clean + value and exit immediately. + */ if (mi->rli.log_space_limit && mi->rli.log_space_limit < mi->rli.log_space_total && !mi->rli.ignore_log_space_limit) @@ -2489,7 +2503,9 @@ slave_begin: pthread_cond_broadcast(&rli->start_cond); //tell the I/O thread to take relay_log_space_limit into account from now on + pthread_mutex_lock(&rli->log_space_lock); rli->ignore_log_space_limit= 0; + pthread_mutex_unlock(&rli->log_space_lock); if (init_relay_log_pos(rli, rli->group_relay_log_name, @@ -3221,7 +3237,12 @@ Log_event* next_event(RELAY_LOG_INFO* rli) pthread_mutex_lock(&rli->log_space_lock); // prevent the I/O thread from blocking next times rli->ignore_log_space_limit= 1; - // If the I/O thread is blocked, unblock it + /* + If the I/O thread is blocked, unblock it. + Ok to broadcast after unlock, because the mutex is only destroyed in + ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be + destroyed before we exit the present function. + */ pthread_mutex_unlock(&rli->log_space_lock); pthread_cond_broadcast(&rli->log_space_cond); // Note that wait_for_update unlocks lock_log ! diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 7a154d206ef..ac6471e794c 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -739,7 +739,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg) query_cache_size_arg)); free_cache(0); query_cache_size= query_cache_size_arg; - DBUG_RETURN(init_cache()); + DBUG_RETURN(::query_cache_size= init_cache()); } @@ -1318,6 +1318,12 @@ ulong Query_cache::init_cache() mem_bin_steps = 1; mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2; prev_size = 0; + if (mem_bin_size <= min_allocation_unit) + { + DBUG_PRINT("qcache", ("too small query cache => query cache disabled")); + // TODO here (and above) should be warning in 4.1 + goto err; + } while (mem_bin_size > min_allocation_unit) { mem_bin_num += mem_bin_count; @@ -1344,14 +1350,6 @@ ulong Query_cache::init_cache() query_cache_size -= additional_data_size; STRUCT_LOCK(&structure_guard_mutex); - if (max_mem_bin_size <= min_allocation_unit) - { - DBUG_PRINT("qcache", - (" max bin size (%lu) <= min_allocation_unit => cache disabled", - max_mem_bin_size)); - STRUCT_UNLOCK(&structure_guard_mutex); - goto err; - } if (!(cache = (byte *) my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1908f898a27..69382b2db95 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1421,6 +1421,24 @@ void select_insert::send_error(uint errcode,const char *err) ::send_error(thd,errcode,err); table->file->extra(HA_EXTRA_NO_CACHE); table->file->activate_all_index(thd); + /* + If at least one row has been inserted/modified and will stay in the table + (the table doesn't have transactions) (example: we got a duplicate key + error while inserting into a MyISAM table) we must write to the binlog (and + the error code will make the slave stop). + */ + if ((info.copied || info.deleted) && !table->file->has_transactions()) + { + if (last_insert_id) + thd->insert_id(last_insert_id); // For binary log + mysql_update_log.write(thd,thd->query,thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, + table->file->has_transactions()); + mysql_bin_log.write(&qinfo); + } + } if (info.copied || info.deleted) query_cache_invalidate3(thd, table, 1); ha_rollback_stmt(thd); @@ -1442,7 +1460,10 @@ bool select_insert::send_eof() if (info.copied || info.deleted) query_cache_invalidate3(thd, table, 1); + if (last_insert_id) + thd->insert_id(last_insert_id); // For binary log /* Write to binlog before commiting transaction */ + mysql_update_log.write(thd,thd->query,thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, @@ -1467,10 +1488,7 @@ bool select_insert::send_eof() else sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, thd->cuted_fields); - if (last_insert_id) - thd->insert_id(last_insert_id); // For update log ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff); - mysql_update_log.write(thd,thd->query,thd->query_length); return 0; } } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7cadf187181..c15c824f843 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1081,58 +1081,76 @@ mysql_rename_table(enum db_type base, } /* - close table in this thread and force close + reopen in other threads - This assumes that the calling thread has lock on LOCK_open - Win32 clients must also have a WRITE LOCK on the table ! + Force all other threads to stop using the table + + SYNOPSIS + wait_while_table_is_used() + thd Thread handler + table Table to remove from cache + + NOTES + When returning, the table will be unusable for other threads until + the table is closed. + + PREREQUISITES + Lock on LOCK_open + Win32 clients must also have a WRITE LOCK on the table ! */ -static void safe_remove_from_cache(THD *thd,TABLE *table) +static void wait_while_table_is_used(THD *thd,TABLE *table) { - DBUG_ENTER("safe_remove_from_cache"); - if (table) - { - DBUG_PRINT("enter",("table: %s", table->real_name)); - VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files - /* Mark all tables that are in use as 'old' */ - mysql_lock_abort(thd,table); // end threads waiting on lock + DBUG_PRINT("enter",("table: %s", table->real_name)); + DBUG_ENTER("wait_while_table_is_used"); + safe_mutex_assert_owner(&LOCK_open); -#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2) - /* Wait until all there are no other threads that has this table open */ - while (remove_table_from_cache(thd,table->table_cache_key, - table->real_name)) - { - dropping_tables++; - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - dropping_tables--; - } -#else - (void) remove_table_from_cache(thd,table->table_cache_key, - table->real_name); -#endif - /* When lock on LOCK_open is freed other threads can continue */ - pthread_cond_broadcast(&COND_refresh); + VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files + /* Mark all tables that are in use as 'old' */ + mysql_lock_abort(thd, table); // end threads waiting on lock + + /* Wait until all there are no other threads that has this table open */ + while (remove_table_from_cache(thd,table->table_cache_key, + table->real_name)) + { + dropping_tables++; + (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + dropping_tables--; } DBUG_VOID_RETURN; } +/* + Close a cached table -bool close_cached_table(THD *thd,TABLE *table) + SYNOPSIS + clsoe_cached_table() + thd Thread handler + table Table to remove from cache + + NOTES + Function ends by signaling threads waiting for the table to try to + reopen the table. + + PREREQUISITES + Lock on LOCK_open + Win32 clients must also have a WRITE LOCK on the table ! +*/ + +static bool close_cached_table(THD *thd, TABLE *table) { DBUG_ENTER("close_cached_table"); - safe_mutex_assert_owner(&LOCK_open); - - if (table) + + wait_while_table_is_used(thd,table); + /* Close lock if this is not got with LOCK TABLES */ + if (thd->lock) { - safe_remove_from_cache(thd,table); - /* Close lock if this is not got with LOCK TABLES */ - if (thd->lock) - { - mysql_unlock_tables(thd, thd->lock); - thd->lock=0; // Start locked threads - } - /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ - thd->open_tables=unlink_open_table(thd,thd->open_tables,table); + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; // Start locked threads } + /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ + thd->open_tables=unlink_open_table(thd,thd->open_tables,table); + + /* When lock on LOCK_open is freed other threads can continue */ + pthread_cond_broadcast(&COND_refresh); DBUG_RETURN(0); } @@ -1261,10 +1279,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); - pthread_mutex_lock(&LOCK_open); - close_cached_table(thd,table_list->table); - pthread_mutex_unlock(&LOCK_open); - + /* If we could open the table, close it */ + if (table_list->table) + { + pthread_mutex_lock(&LOCK_open); + close_cached_table(thd, table); + pthread_mutex_unlock(&LOCK_open); + } if (lock_and_wait_for_table_name(thd,table_list)) { error= -1; @@ -1794,11 +1815,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, else { *fn_ext(new_name)=0; - close_cached_table(thd,table); + close_cached_table(thd, table); if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name)) error= -1; } - VOID(pthread_cond_broadcast(&COND_refresh)); VOID(pthread_mutex_unlock(&LOCK_open)); } if (!error) @@ -1807,12 +1827,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, case LEAVE_AS_IS: break; case ENABLE: - safe_remove_from_cache(thd,table); - error= table->file->activate_all_index(thd); + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table); + VOID(pthread_mutex_unlock(&LOCK_open)); + error= table->file->activate_all_index(thd); + /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: - safe_remove_from_cache(thd,table); + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table); + VOID(pthread_mutex_unlock(&LOCK_open)); table->file->deactivate_non_unique_index(HA_POS_ERROR); + /* COND_refresh will be signaled in close_thread_tables() */ break; } } @@ -2247,7 +2273,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, close the original table at before doing the rename */ table_name=thd->strdup(table_name); // must be saved - if (close_cached_table(thd,table)) + if (close_cached_table(thd, table)) { // Aborted VOID(quick_rm_table(new_db_type,new_db,tmp_name)); VOID(pthread_mutex_unlock(&LOCK_open)); @@ -2281,7 +2307,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, This shouldn't happen. We solve this the safe way by closing the locked table. */ - close_cached_table(thd,table); + if (table) + close_cached_table(thd,table); VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } @@ -2291,7 +2318,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, Not table locking or alter table with rename free locks and remove old table */ - close_cached_table(thd,table); + if (table) + close_cached_table(thd,table); VOID(quick_rm_table(old_db_type,db,old_name)); } else @@ -2311,7 +2339,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, if (close_data_tables(thd,db,table_name) || reopen_tables(thd,1,0)) { // This shouldn't happen - close_cached_table(thd,table); // Remove lock for table + if (table) + close_cached_table(thd,table); // Remove lock for table VOID(pthread_mutex_unlock(&LOCK_open)); goto err; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1f6364ec427..989d17b006b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -200,7 +200,6 @@ int mysql_update(THD *thd, */ uint length; SORT_FIELD *sortorder; - List<Item> fields; ha_rows examined_rows; table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index efb5e42626d..e96c87b3f43 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4324,6 +4324,7 @@ keyword: | SHARE_SYM {} | SHUTDOWN {} | SLAVE {} + | SOUNDS_SYM {} | SQL_CACHE_SYM {} | SQL_BUFFER_RESULT {} | SQL_NO_CACHE_SYM {} @@ -4348,8 +4349,8 @@ keyword: | VARIABLES {} | VALUE_SYM {} | WORK_SYM {} + | X509_SYM {} | YEAR_SYM {} - | SOUNDS_SYM {} ; /* Option functions */ diff --git a/sql/time.cc b/sql/time.cc index eba664a690d..b6ca306e523 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037 /* Currently only my_time_zone is inited */ static long my_time_zone=0; -pthread_mutex_t LOCK_timezone; void init_time(void) { @@ -39,14 +38,14 @@ void init_time(void) seconds= (time_t) time((time_t*) 0); localtime_r(&seconds,&tm_tmp); l_time= &tm_tmp; - my_time_zone=0; + my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */ my_time.year= (uint) l_time->tm_year+1900; my_time.month= (uint) l_time->tm_mon+1; my_time.day= (uint) l_time->tm_mday; my_time.hour= (uint) l_time->tm_hour; my_time.minute= (uint) l_time->tm_min; - my_time.second= (uint) l_time->tm_sec; - VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */ + my_time.second= (uint) l_time->tm_sec; + my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */ } /* @@ -57,26 +56,39 @@ void init_time(void) */ -long my_gmt_sec(TIME *t) +long my_gmt_sec(TIME *t, long *my_timezone) { uint loop; time_t tmp; struct tm *l_time,tm_tmp; - long diff; + long diff, current_timezone; if (t->hour >= 24) { /* Fix for time-loop */ t->day+=t->hour/24; t->hour%=24; } - pthread_mutex_lock(&LOCK_timezone); - tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - - (long) days_at_timestart)*86400L + (long) t->hour*3600L + - (long) (t->minute*60 + t->second)) + (time_t) my_time_zone; + + /* + Calculate the gmt time based on current time and timezone + The -1 on the end is to ensure that if have a date that exists twice + (like 2002-10-27 02:00:0 MET), we will find the initial date. + + By doing -3600 we will have to call localtime_r() several times, but + I couldn't come up with a better way to get a repeatable result :( + + We can't use mktime() as it's buggy on many platforms and not thread safe. + */ + tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - + (long) days_at_timestart)*86400L + (long) t->hour*3600L + + (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - + 3600); + current_timezone= my_time_zone; + localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; for (loop=0; - loop < 3 && + loop < 2 && (t->hour != (uint) l_time->tm_hour || t->minute != (uint) l_time->tm_min); loop++) @@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t) days= -1; diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + (long) (60*((int) t->minute - (int) l_time->tm_min))); - my_time_zone+=diff; - tmp+=(time_t) diff; + current_timezone+= diff+3600; // Compensate for -3600 above + tmp+= (time_t) diff; localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; } - /* Fix that if we are in the not existing daylight saving time hour - we move the start of the next real hour */ - if (loop == 3 && t->hour != (uint) l_time->tm_hour) + /* + Fix that if we are in the not existing daylight saving time hour + we move the start of the next real hour + */ + if (loop == 2 && t->hour != (uint) l_time->tm_hour) { int days= t->day - l_time->tm_mday; if (days < -1) @@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t) if (diff == 3600) tmp+=3600 - t->minute*60 - t->second; // Move to next hour else if (diff == -3600) - tmp-=t->minute*60 + t->second; // Move to next hour + tmp-=t->minute*60 + t->second; // Move to previous hour } - if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12) - my_time_zone=0; /* Wrong date */ - pthread_mutex_unlock(&LOCK_timezone); + *my_timezone= current_timezone; return (long) tmp; } /* my_gmt_sec */ @@ -428,6 +440,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) time_t str_to_timestamp(const char *str,uint length) { TIME l_time; + long not_used; + if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) return(0); if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) @@ -435,7 +449,7 @@ time_t str_to_timestamp(const char *str,uint length) current_thd->cuted_fields++; return(0); } - return(my_gmt_sec(&l_time)); + return(my_gmt_sec(&l_time, ¬_used)); } |