List:Commits« Previous MessageNext Message »
From:marko.makela Date:October 19 2010 9:22am
Subject:bzr push into mysql-trunk-innodb branch (marko.makela:3251 to 3252)
View as plain text  
 3252 Marko Mäkelä	2010-10-19 [merge]
      Merge from mysql-5.5-innodb

    modified:
      storage/innobase/include/os0sync.h
      storage/innobase/include/srv0srv.h
      storage/innobase/log/log0log.c
      storage/innobase/os/os0sync.c
      storage/innobase/srv/srv0srv.c
 3251 Vasil Dimov	2010-10-19 [merge]
      Merge mysql-5.5-innodb -> mysql-trunk-innodb

    added:
      mysql-test/suite/innodb/r/innodb_bug56632.result
      mysql-test/suite/innodb/t/innodb_bug56632.test
    modified:
      storage/innobase/handler/ha_innodb.cc
=== modified file 'storage/innobase/include/os0sync.h'
--- a/storage/innobase/include/os0sync.h	revid:vasil.dimov@stripped18-zsasadnzch4ou4vl
+++ b/storage/innobase/include/os0sync.h	revid:marko.makela@stripped2y58vh0h
@@ -76,6 +76,12 @@ struct os_event_struct {
 					/*!< list of all created events */
 };
 
+/** Denotes an infinite delay for os_event_wait_time() */
+#define OS_SYNC_INFINITE_TIME   ULINT_UNDEFINED
+
+/** Return value of os_event_wait_time() when the time is exceeded */
+#define OS_SYNC_TIME_EXCEEDED   1
+
 /** Operating system mutex */
 typedef struct os_mutex_struct	os_mutex_str_t;
 /** Operating system mutex handle */
@@ -173,7 +179,23 @@ os_event_wait_low(
 					os_event_reset(). */
 
 #define os_event_wait(event) os_event_wait_low(event, 0)
+#define os_event_wait_time(e, t) os_event_wait_time_low(event, t, 0)
 
+/**********************************************************//**
+Waits for an event object until it is in the signaled state or
+a timeout is exceeded. In Unix the timeout is always infinite.
+@return	0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+UNIV_INTERN
+ulint
+os_event_wait_time_low(
+/*===================*/
+	os_event_t	event,			/*!< in: event to wait */
+	ulint		time_in_usec,		/*!< in: timeout in
+						microseconds, or
+						OS_SYNC_INFINITE_TIME */
+	ib_int64_t	reset_sig_count);	/*!< in: zero or the value
+						returned by previous call of
+						os_event_reset(). */
 /*********************************************************//**
 Creates an operating system mutex semaphore. Because these are slow, the
 mutex semaphore of InnoDB itself (mutex_t) should be used where possible.

=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h	revid:vasil.dimov@strippedsadnzch4ou4vl
+++ b/storage/innobase/include/srv0srv.h	revid:marko.makela@stripped0h
@@ -57,6 +57,15 @@ extern const char	srv_mysql50_table_name
 thread starts running */
 extern os_event_t	srv_lock_timeout_thread_event;
 
+/* The monitor thread waits on this event. */
+extern os_event_t	srv_monitor_event;
+
+/* The lock timeout thread waits on this event. */
+extern os_event_t	srv_timeout_event;
+
+/* The error monitor thread waits on this event. */
+extern os_event_t	srv_error_event;
+
 /* If the last data file is auto-extended, we add this many pages to it
 at a time */
 #define SRV_AUTO_EXTEND_INCREMENT	\

=== modified file 'storage/innobase/log/log0log.c'
--- a/storage/innobase/log/log0log.c	revid:vasil.dimov@stripped
+++ b/storage/innobase/log/log0log.c	revid:marko.makela@oracle.com-20101019091242-hais946k2y58vh0h
@@ -3137,14 +3137,17 @@ loop:
 	proceed without waiting for monitor threads. */
 
 	if (srv_fast_shutdown < 2
-	   && (srv_error_monitor_active
-	      || srv_lock_timeout_active || srv_monitor_active)) {
-		const char*	thread_active = NULL;
+	    && (srv_error_monitor_active
+		|| srv_lock_timeout_active
+		|| srv_monitor_active)) {
+
+		mutex_exit(&kernel_mutex);
 
 		/* Print a message every 60 seconds if we are waiting
 		for the monitor thread to exit. Master and worker threads
 		check will be done later. */
 		if (srv_print_verbose_log && count > 600) {
+			const char*	thread_active = NULL;
 
 			if (srv_error_monitor_active) {
 				thread_active = "srv_error_monitor_thread";
@@ -3153,17 +3156,19 @@ loop:
 			} else if (srv_monitor_active) {
 				thread_active = "srv_monitor_thread";
 			}
-		}
 
-		mutex_exit(&kernel_mutex);
-
-		if (thread_active) {
-			ut_print_timestamp(stderr);
-			fprintf(stderr, "  InnoDB: Waiting for %s "
-				"to exit\n", thread_active);
-			count = 0;
+			if (thread_active) {
+				ut_print_timestamp(stderr);
+				fprintf(stderr, "  InnoDB: Waiting for %s "
+					"to exit\n", thread_active);
+				count = 0;
+			}
 		}
 
+		os_event_set(srv_error_event);
+		os_event_set(srv_monitor_event);
+		os_event_set(srv_timeout_event);
+
 		goto loop;
 	}
 
@@ -3199,6 +3204,8 @@ loop:
 
 		log_buffer_flush_to_disk();
 
+		mutex_exit(&kernel_mutex);
+
 		return; /* We SKIP ALL THE REST !! */
 	}
 

=== modified file 'storage/innobase/os/os0sync.c'
--- a/storage/innobase/os/os0sync.c	revid:vasil.dimov@oracle.com-20101019083618-zsasadnzch4ou4vl
+++ b/storage/innobase/os/os0sync.c	revid:marko.makela@stripped42-hais946k2y58vh0h
@@ -72,6 +72,9 @@ UNIV_INTERN ulint	os_event_count		= 0;
 UNIV_INTERN ulint	os_mutex_count		= 0;
 UNIV_INTERN ulint	os_fast_mutex_count	= 0;
 
+/* The number of microsecnds in a second. */
+static const ulint MICROSECS_IN_A_SECOND = 1000000;
+
 /* Because a mutex is embedded inside an event and there is an
 event embedded inside a mutex, on free, this generates a recursive call.
 This version of the free event function doesn't acquire the global lock */
@@ -122,6 +125,47 @@ os_cond_init(
 }
 
 /*********************************************************//**
+Do a timed wait on condition variable.
+@return TRUE if timed out, FALSE otherwise */
+UNIV_INLINE
+ibool
+os_cond_wait_timed(
+/*===============*/
+	os_cond_t*		cond,		/*!< in: condition variable. */
+	os_fast_mutex_t*	mutex,		/*!< in: fast mutex */
+#ifndef __WIN__
+	const struct timespec*	abstime		/*!< in: timeout */
+#else
+	ulint			time_in_ms	/*!< in: timeout in
+						milliseconds */
+#endif /* !__WIN__ */
+)
+{
+#ifdef __WIN__
+	BOOL			ret;
+
+	ut_a(sleep_condition_variable != NULL);
+
+	ret = sleep_condition_variable(cond, mutex, time_in_ms);
+
+	if (!ret && GetLastError() == WAIT_TIMEOUT) {
+		return(TRUE);
+	}
+
+	ut_a(ret);
+
+	return(FALSE);
+#else
+	int	ret;
+
+	ret = pthread_cond_timedwait(cond, mutex, abstime);
+
+	ut_a(ret == 0 || ret == ETIMEDOUT);
+
+	return(ret == ETIMEDOUT);
+#endif
+}
+/*********************************************************//**
 Wait on condition variable */
 UNIV_INLINE
 void
@@ -572,6 +616,113 @@ os_event_wait_low(
 	}
 }
 
+/**********************************************************//**
+Waits for an event object until it is in the signaled state or
+a timeout is exceeded.
+@return	0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+UNIV_INTERN
+ulint
+os_event_wait_time_low(
+/*===================*/
+	os_event_t	event,			/*!< in: event to wait */
+	ulint		time_in_usec,		/*!< in: timeout in
+						microseconds, or
+						OS_SYNC_INFINITE_TIME */
+	ib_int64_t	reset_sig_count)	/*!< in: zero or the value
+						returned by previous call of
+						os_event_reset(). */
+
+{
+	ibool		timed_out;
+	ib_int64_t	old_signal_count;
+
+#ifdef __WIN__
+	DWORD		time_in_ms = time_in_usec / 1000;
+
+	if (!srv_use_native_conditions) {
+		DWORD	err;
+
+		ut_a(event);
+
+		if (time_in_ms != OS_SYNC_INFINITE_TIME) {
+			err = WaitForSingleObject(event->handle, time_in_ms);
+		} else {
+			err = WaitForSingleObject(event->handle, INFINITE);
+		}
+
+		if (err == WAIT_OBJECT_0) {
+			return(0);
+		} else if (err == WAIT_TIMEOUT) {
+			return(OS_SYNC_TIME_EXCEEDED);
+		}
+
+		ut_error;
+		/* Dummy value to eliminate compiler warning. */
+		return(42);
+	} else {
+		ut_a(sleep_condition_variable != NULL);
+	}
+#else
+	struct timeval	tv;
+	ulint		sec;
+	ulint		usec;
+	int		ret;
+	struct timespec	abstime;
+
+	ret = ut_usectime(&sec, &usec);
+	ut_a(ret == 0);
+
+	tv.tv_sec = sec;
+	tv.tv_usec = usec;
+
+	tv.tv_usec += time_in_usec;
+
+	if ((ulint) tv.tv_usec > MICROSECS_IN_A_SECOND) {
+		tv.tv_sec += time_in_usec / MICROSECS_IN_A_SECOND;
+		tv.tv_usec %= MICROSECS_IN_A_SECOND;
+	}
+
+	/* Convert to nano seconds. We ignore overflow. */
+	abstime.tv_sec  = tv.tv_sec;
+	abstime.tv_nsec = tv.tv_usec * 1000;
+#endif /* __WIN__ */
+
+	os_fast_mutex_lock(&event->os_mutex);
+
+	if (reset_sig_count) {
+		old_signal_count = reset_sig_count;
+	} else {
+		old_signal_count = event->signal_count;
+	}
+
+	do {
+		if (event->is_set == TRUE
+		    || event->signal_count != old_signal_count) {
+
+			break;
+		}
+
+		timed_out = os_cond_wait_timed(
+			&event->cond_var, &event->os_mutex,
+#ifndef __WIN__
+			&abstime
+#else
+			time_in_ms
+#endif /* !__WIN__ */
+		);
+
+	} while (!timed_out);
+
+	os_fast_mutex_unlock(&event->os_mutex);
+
+	if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+
+		os_thread_exit(NULL);
+	}
+
+	return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0);
+}
+
 /*********************************************************//**
 Creates an operating system mutex semaphore. Because these are slow, the
 mutex semaphore of InnoDB itself (mutex_t) should be used where possible.

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	revid:vasil.dimov@stripped8-zsasadnzch4ou4vl
+++ b/storage/innobase/srv/srv0srv.c	revid:marko.makela@strippedh0h
@@ -698,6 +698,12 @@ struct srv_slot_struct{
 /* Table for MySQL threads where they will be suspended to wait for locks */
 UNIV_INTERN srv_slot_t*	srv_mysql_table = NULL;
 
+UNIV_INTERN os_event_t	srv_timeout_event;
+
+UNIV_INTERN os_event_t	srv_monitor_event;
+
+UNIV_INTERN os_event_t	srv_error_event;
+
 UNIV_INTERN os_event_t	srv_lock_timeout_thread_event;
 
 UNIV_INTERN srv_sys_t*	srv_sys	= NULL;
@@ -1015,6 +1021,12 @@ srv_init(void)
 		ut_a(slot->event);
 	}
 
+	srv_error_event = os_event_create(NULL);
+
+	srv_timeout_event = os_event_create(NULL);
+
+	srv_monitor_event = os_event_create(NULL);
+
 	srv_lock_timeout_thread_event = os_event_create(NULL);
 
 	for (i = 0; i < SRV_MASTER + 1; i++) {
@@ -2041,6 +2053,7 @@ srv_monitor_thread(
 			/*!< in: a dummy parameter required by
 			os_thread_create */
 {
+	ib_int64_t	sig_count;
 	double		time_elapsed;
 	time_t		current_time;
 	time_t		last_table_monitor_time;
@@ -2059,26 +2072,28 @@ srv_monitor_thread(
 #endif
 
 	UT_NOT_USED(arg);
-	srv_last_monitor_time = time(NULL);
-	last_table_monitor_time = time(NULL);
-	last_tablespace_monitor_time = time(NULL);
-	last_monitor_time = time(NULL);
+	srv_last_monitor_time = ut_time();
+	last_table_monitor_time = ut_time();
+	last_tablespace_monitor_time = ut_time();
+	last_monitor_time = ut_time();
 	mutex_skipped = 0;
 	last_srv_print_monitor = srv_print_innodb_monitor;
 loop:
 	srv_monitor_active = TRUE;
 
 	/* Wake up every 5 seconds to see if we need to print
-	monitor information. */
+	monitor information or if signalled at shutdown. */
 
-	os_thread_sleep(5000000);
+	sig_count = os_event_reset(srv_monitor_event);
 
-	current_time = time(NULL);
+	os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
+
+	current_time = ut_time();
 
 	time_elapsed = difftime(current_time, last_monitor_time);
 
 	if (time_elapsed > 15) {
-		last_monitor_time = time(NULL);
+		last_monitor_time = ut_time();
 
 		if (srv_print_innodb_monitor) {
 			/* Reset mutex_skipped counter everytime
@@ -2122,7 +2137,7 @@ loop:
 		if (srv_print_innodb_tablespace_monitor
 		    && difftime(current_time,
 				last_tablespace_monitor_time) > 60) {
-			last_tablespace_monitor_time = time(NULL);
+			last_tablespace_monitor_time = ut_time();
 
 			fputs("========================"
 			      "========================\n",
@@ -2148,7 +2163,7 @@ loop:
 		if (srv_print_innodb_table_monitor
 		    && difftime(current_time, last_table_monitor_time) > 60) {
 
-			last_table_monitor_time = time(NULL);
+			last_table_monitor_time = ut_time();
 
 			fputs("===========================================\n",
 			      stderr);
@@ -2208,16 +2223,20 @@ srv_lock_timeout_thread(
 	ibool		some_waits;
 	double		wait_time;
 	ulint		i;
+	ib_int64_t	sig_count;
 
 #ifdef UNIV_PFS_THREAD
 	pfs_register_thread(srv_lock_timeout_thread_key);
 #endif
 
 loop:
+
 	/* When someone is waiting for a lock, we wake up every second
 	and check if a timeout has passed for a lock wait */
 
-	os_thread_sleep(1000000);
+	sig_count = os_event_reset(srv_timeout_event);
+
+	os_event_wait_time_low(srv_timeout_event, 1000000, sig_count);
 
 	srv_lock_timeout_active = TRUE;
 
@@ -2313,6 +2332,7 @@ srv_error_monitor_thread(
 	ulint		fatal_cnt	= 0;
 	ib_uint64_t	old_lsn;
 	ib_uint64_t	new_lsn;
+	ib_int64_t	sig_count;
 
 	old_lsn = srv_start_lsn;
 
@@ -2388,7 +2408,9 @@ loop:
 
 	fflush(stderr);
 
-	os_thread_sleep(1000000);
+	sig_count = os_event_reset(srv_error_event);
+
+	os_event_wait_time_low(srv_error_event, 1000000, sig_count);
 
 	if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
 
@@ -2701,6 +2723,21 @@ loop:
 	for (i = 0; i < 10; i++) {
 		ulint	cur_time = ut_time_ms();
 
+		/* ALTER TABLE in MySQL requires on Unix that the table handler
+		can drop tables lazily after there no longer are SELECT
+		queries to them. */
+
+		srv_main_thread_op_info = "doing background drop tables";
+
+		row_drop_tables_for_mysql_in_background();
+
+		srv_main_thread_op_info = "";
+
+		if (srv_fast_shutdown && srv_shutdown_state > 0) {
+
+			goto background_loop;
+		}
+
 		buf_get_total_stat(&buf_stat);
 
 		n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
@@ -2709,7 +2746,8 @@ loop:
 		srv_main_thread_op_info = "sleeping";
 		srv_main_1_second_loops++;
 
-		if (next_itr_time > cur_time) {
+		if (next_itr_time > cur_time
+		    && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
 
 			/* Get sleep interval in micro seconds. We use
 			ut_min() to avoid long sleep in case of
@@ -2723,21 +2761,6 @@ loop:
 		/* Each iteration should happen at 1 second interval. */
 		next_itr_time = ut_time_ms() + 1000;
 
-		/* ALTER TABLE in MySQL requires on Unix that the table handler
-		can drop tables lazily after there no longer are SELECT
-		queries to them. */
-
-		srv_main_thread_op_info = "doing background drop tables";
-
-		row_drop_tables_for_mysql_in_background();
-
-		srv_main_thread_op_info = "";
-
-		if (srv_fast_shutdown && srv_shutdown_state > 0) {
-
-			goto background_loop;
-		}
-
 		/* Flush logs if needed */
 		srv_sync_log_buffer_in_background();
 
@@ -2929,7 +2952,9 @@ background_loop:
 		MySQL tries to drop a table while there are still open handles
 		to it and we had to put it to the background drop queue.) */
 
-		os_thread_sleep(100000);
+		if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
+			os_thread_sleep(100000);
+		}
 	}
 
 	if (srv_n_purge_threads == 0) {

Attachment: [text/bzr-bundle] bzr/marko.makela@oracle.com-20101019091242-hais946k2y58vh0h.bundle
Thread
bzr push into mysql-trunk-innodb branch (marko.makela:3251 to 3252) marko.makela19 Oct