mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
Merge with 4.0.13
This commit is contained in:
commit
7a54334443
27 changed files with 572 additions and 301 deletions
|
@ -100,7 +100,7 @@ typedef struct st_alarm {
|
||||||
#define thr_alarm_init(A) (*(A))=0
|
#define thr_alarm_init(A) (*(A))=0
|
||||||
#define thr_alarm_in_use(A) (*(A)!= 0)
|
#define thr_alarm_in_use(A) (*(A)!= 0)
|
||||||
void init_thr_alarm(uint max_alarm);
|
void init_thr_alarm(uint max_alarm);
|
||||||
bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
|
my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
|
||||||
void thr_alarm_kill(pthread_t thread_id);
|
void thr_alarm_kill(pthread_t thread_id);
|
||||||
void thr_end_alarm(thr_alarm_t *alarmed);
|
void thr_end_alarm(thr_alarm_t *alarmed);
|
||||||
void end_thr_alarm(my_bool free_structures);
|
void end_thr_alarm(my_bool free_structures);
|
||||||
|
|
|
@ -103,7 +103,8 @@ struct com_shm_endpoint_struct{
|
||||||
the area currently may contain a datagram;
|
the area currently may contain a datagram;
|
||||||
NOTE: automatic event */
|
NOTE: automatic event */
|
||||||
os_event_t empty; /* this is in the signaled state if the area
|
os_event_t empty; /* this is in the signaled state if the area
|
||||||
currently may be empty; NOTE: automatic event */
|
currently may be empty; NOTE: automatic
|
||||||
|
event */
|
||||||
ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex
|
ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex
|
||||||
protecting the shared memory */
|
protecting the shared memory */
|
||||||
UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct
|
UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct
|
||||||
|
@ -793,16 +794,18 @@ com_shm_create_or_open(
|
||||||
|
|
||||||
ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"),
|
ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"),
|
||||||
|
|
||||||
event_ne = os_event_create_auto(buf);
|
event_ne = os_event_create(buf);
|
||||||
|
|
||||||
ut_ad(event_ne);
|
ut_ad(event_ne);
|
||||||
|
|
||||||
ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"),
|
ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"),
|
||||||
|
|
||||||
event_em = os_event_create_auto(buf);
|
event_em = os_event_create(buf);
|
||||||
|
|
||||||
ut_ad(event_em);
|
ut_ad(event_em);
|
||||||
|
|
||||||
|
ut_a(0); /* event_ne and event_em should be auto events! */
|
||||||
|
|
||||||
com_shm_endpoint_set_shm(ep, shm);
|
com_shm_endpoint_set_shm(ep, shm);
|
||||||
com_shm_endpoint_set_map(ep, map);
|
com_shm_endpoint_set_map(ep, map);
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,26 @@ Created 9/6/1995 Heikki Tuuri
|
||||||
#include "ut0lst.h"
|
#include "ut0lst.h"
|
||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
|
|
||||||
#define os_fast_mutex_t CRITICAL_SECTION
|
#define os_fast_mutex_t CRITICAL_SECTION
|
||||||
typedef HANDLE os_event_t;
|
|
||||||
|
typedef HANDLE os_native_event_t;
|
||||||
|
|
||||||
|
typedef struct os_event_struct os_event_struct_t;
|
||||||
|
typedef os_event_struct_t* os_event_t;
|
||||||
|
|
||||||
|
struct os_event_struct {
|
||||||
|
os_native_event_t handle;
|
||||||
|
/* Windows event */
|
||||||
|
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
|
||||||
|
/* list of all created events */
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
typedef pthread_mutex_t os_fast_mutex_t;
|
typedef pthread_mutex_t os_fast_mutex_t;
|
||||||
|
|
||||||
typedef struct os_event_struct os_event_struct_t;
|
typedef struct os_event_struct os_event_struct_t;
|
||||||
typedef os_event_struct_t* os_event_t;
|
typedef os_event_struct_t* os_event_t;
|
||||||
|
|
||||||
struct os_event_struct {
|
struct os_event_struct {
|
||||||
os_fast_mutex_t os_mutex; /* this mutex protects the next
|
os_fast_mutex_t os_mutex; /* this mutex protects the next
|
||||||
fields */
|
fields */
|
||||||
|
@ -39,16 +52,16 @@ typedef os_mutex_str_t* os_mutex_t;
|
||||||
|
|
||||||
#define OS_SYNC_TIME_EXCEEDED 1
|
#define OS_SYNC_TIME_EXCEEDED 1
|
||||||
|
|
||||||
/* Mutex protecting the thread count and event and OS 'slow' mutex lists */
|
/* Mutex protecting counts and the event and OS 'slow' mutex lists */
|
||||||
extern os_mutex_t os_sync_mutex;
|
extern os_mutex_t os_sync_mutex;
|
||||||
|
|
||||||
/* This is incremented by 1 in os_thread_create and decremented by 1 in
|
/* This is incremented by 1 in os_thread_create and decremented by 1 in
|
||||||
os_thread_exit */
|
os_thread_exit */
|
||||||
extern ulint os_thread_count;
|
extern ulint os_thread_count;
|
||||||
|
|
||||||
/* The following are approximate counters for debugging in Unix */
|
|
||||||
extern ulint os_event_count;
|
extern ulint os_event_count;
|
||||||
extern ulint os_mutex_count;
|
extern ulint os_mutex_count;
|
||||||
|
extern ulint os_fast_mutex_count;
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Initializes global event and OS 'slow' mutex lists. */
|
Initializes global event and OS 'slow' mutex lists. */
|
||||||
|
@ -57,15 +70,14 @@ void
|
||||||
os_sync_init(void);
|
os_sync_init(void);
|
||||||
/*==============*/
|
/*==============*/
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Frees created events (not in Windows) and OS 'slow' mutexes. */
|
Frees created events and OS 'slow' mutexes. */
|
||||||
|
|
||||||
void
|
void
|
||||||
os_sync_free(void);
|
os_sync_free(void);
|
||||||
/*==============*/
|
/*==============*/
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Creates an event semaphore, i.e., a semaphore which may
|
Creates an event semaphore, i.e., a semaphore which may just have two states:
|
||||||
just have two states: signaled and nonsignaled.
|
signaled and nonsignaled. The created event is manual reset: it must be reset
|
||||||
The created event is manual reset: it must be reset
|
|
||||||
explicitly by calling sync_os_reset_event. */
|
explicitly by calling sync_os_reset_event. */
|
||||||
|
|
||||||
os_event_t
|
os_event_t
|
||||||
|
@ -74,10 +86,10 @@ os_event_create(
|
||||||
/* out: the event handle */
|
/* out: the event handle */
|
||||||
char* name); /* in: the name of the event, if NULL
|
char* name); /* in: the name of the event, if NULL
|
||||||
the event is created without a name */
|
the event is created without a name */
|
||||||
|
#ifdef __WIN__
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Creates an auto-reset event semaphore, i.e., an event
|
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
||||||
which is automatically reset when a single thread is
|
reset when a single thread is released. Works only in Windows. */
|
||||||
released. */
|
|
||||||
|
|
||||||
os_event_t
|
os_event_t
|
||||||
os_event_create_auto(
|
os_event_create_auto(
|
||||||
|
@ -85,6 +97,7 @@ os_event_create_auto(
|
||||||
/* out: the event handle */
|
/* out: the event handle */
|
||||||
char* name); /* in: the name of the event, if NULL
|
char* name); /* in: the name of the event, if NULL
|
||||||
the event is created without a name */
|
the event is created without a name */
|
||||||
|
#endif
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
Sets an event semaphore to the signaled state: lets waiting threads
|
Sets an event semaphore to the signaled state: lets waiting threads
|
||||||
proceed. */
|
proceed. */
|
||||||
|
@ -120,7 +133,7 @@ os_event_wait(
|
||||||
os_event_t event); /* in: event to wait */
|
os_event_t event); /* in: event to wait */
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
Waits for an event object until it is in the signaled state or
|
Waits for an event object until it is in the signaled state or
|
||||||
a timeout is exceeded. */
|
a timeout is exceeded. In Unix the timeout is always infinite. */
|
||||||
|
|
||||||
ulint
|
ulint
|
||||||
os_event_wait_time(
|
os_event_wait_time(
|
||||||
|
@ -131,8 +144,9 @@ os_event_wait_time(
|
||||||
os_event_t event, /* in: event to wait */
|
os_event_t event, /* in: event to wait */
|
||||||
ulint time); /* in: timeout in microseconds, or
|
ulint time); /* in: timeout in microseconds, or
|
||||||
OS_SYNC_INFINITE_TIME */
|
OS_SYNC_INFINITE_TIME */
|
||||||
|
#ifdef __WIN__
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
Waits for any event in an event array. Returns if even a single
|
Waits for any event in an OS native event array. Returns if even a single
|
||||||
one is signaled or becomes signaled. */
|
one is signaled or becomes signaled. */
|
||||||
|
|
||||||
ulint
|
ulint
|
||||||
|
@ -142,12 +156,13 @@ os_event_wait_multiple(
|
||||||
which was signaled */
|
which was signaled */
|
||||||
ulint n, /* in: number of events in the
|
ulint n, /* in: number of events in the
|
||||||
array */
|
array */
|
||||||
os_event_t* event_array); /* in: pointer to an array of event
|
os_native_event_t* native_event_array);
|
||||||
|
/* in: pointer to an array of event
|
||||||
handles */
|
handles */
|
||||||
|
#endif
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Creates an operating system mutex semaphore.
|
Creates an operating system mutex semaphore. Because these are slow, the
|
||||||
Because these are slow, the mutex semaphore of the database
|
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
||||||
itself (sync_mutex_t) should be used where possible. */
|
|
||||||
|
|
||||||
os_mutex_t
|
os_mutex_t
|
||||||
os_mutex_create(
|
os_mutex_create(
|
||||||
|
|
|
@ -44,4 +44,3 @@ os_fast_mutex_trylock(
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,9 @@ os_thread_pf(
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
Creates a new thread of execution. The execution starts from
|
Creates a new thread of execution. The execution starts from
|
||||||
the function given. The start function takes a void* parameter
|
the function given. The start function takes a void* parameter
|
||||||
and returns a ulint. */
|
and returns a ulint.
|
||||||
|
NOTE: We count the number of threads in os_thread_exit(). A created
|
||||||
|
thread should always use that to exit and not use return() to exit. */
|
||||||
|
|
||||||
os_thread_t
|
os_thread_t
|
||||||
os_thread_create(
|
os_thread_create(
|
||||||
|
|
|
@ -80,6 +80,8 @@ struct os_aio_slot_struct{
|
||||||
which pending aio operation was
|
which pending aio operation was
|
||||||
completed */
|
completed */
|
||||||
#ifdef WIN_ASYNC_IO
|
#ifdef WIN_ASYNC_IO
|
||||||
|
os_event_t event; /* event object we need in the
|
||||||
|
OVERLAPPED struct */
|
||||||
OVERLAPPED control; /* Windows control block for the
|
OVERLAPPED control; /* Windows control block for the
|
||||||
aio request */
|
aio request */
|
||||||
#elif defined(POSIX_ASYNC_IO)
|
#elif defined(POSIX_ASYNC_IO)
|
||||||
|
@ -107,11 +109,14 @@ struct os_aio_array_struct{
|
||||||
ulint n_reserved;/* Number of reserved slots in the
|
ulint n_reserved;/* Number of reserved slots in the
|
||||||
aio array outside the ibuf segment */
|
aio array outside the ibuf segment */
|
||||||
os_aio_slot_t* slots; /* Pointer to the slots in the array */
|
os_aio_slot_t* slots; /* Pointer to the slots in the array */
|
||||||
os_event_t* events; /* Pointer to an array of event handles
|
#ifdef __WIN__
|
||||||
where we copied the handles from slots,
|
os_native_event_t* native_events;
|
||||||
in the same order. This can be used in
|
/* Pointer to an array of OS native event
|
||||||
WaitForMultipleObjects; used only in
|
handles where we copied the handles from
|
||||||
|
slots, in the same order. This can be used
|
||||||
|
in WaitForMultipleObjects; used only in
|
||||||
Windows */
|
Windows */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Array of events used in simulated aio */
|
/* Array of events used in simulated aio */
|
||||||
|
@ -296,7 +301,7 @@ os_file_handle_error(
|
||||||
operation */
|
operation */
|
||||||
os_file_t file, /* in: file pointer */
|
os_file_t file, /* in: file pointer */
|
||||||
char* name, /* in: name of a file or NULL */
|
char* name, /* in: name of a file or NULL */
|
||||||
const char* operation) /* in: type of operation */
|
const char* operation)/* in: operation */
|
||||||
{
|
{
|
||||||
ulint err;
|
ulint err;
|
||||||
|
|
||||||
|
@ -338,8 +343,8 @@ os_file_handle_error(
|
||||||
if (name) {
|
if (name) {
|
||||||
fprintf(stderr, "InnoDB: File name %s\n", name);
|
fprintf(stderr, "InnoDB: File name %s\n", name);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "InnoDB: system call %s\n", operation);
|
|
||||||
|
|
||||||
|
fprintf(stderr, "InnoDB: System call %s.\n", operation);
|
||||||
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
|
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
|
||||||
|
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
@ -424,7 +429,6 @@ try_again:
|
||||||
retry = os_file_handle_error(file, name,
|
retry = os_file_handle_error(file, name,
|
||||||
create_mode == OS_FILE_OPEN ?
|
create_mode == OS_FILE_OPEN ?
|
||||||
"open" : "create");
|
"open" : "create");
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
@ -467,8 +471,6 @@ try_again:
|
||||||
retry = os_file_handle_error(file, name,
|
retry = os_file_handle_error(file, name,
|
||||||
create_mode == OS_FILE_OPEN ?
|
create_mode == OS_FILE_OPEN ?
|
||||||
"open" : "create");
|
"open" : "create");
|
||||||
|
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
@ -578,7 +580,6 @@ try_again:
|
||||||
retry = os_file_handle_error(file, name,
|
retry = os_file_handle_error(file, name,
|
||||||
create_mode == OS_FILE_OPEN ?
|
create_mode == OS_FILE_OPEN ?
|
||||||
"open" : "create");
|
"open" : "create");
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
@ -627,7 +628,6 @@ try_again:
|
||||||
retry = os_file_handle_error(file, name,
|
retry = os_file_handle_error(file, name,
|
||||||
create_mode == OS_FILE_OPEN ?
|
create_mode == OS_FILE_OPEN ?
|
||||||
"open" : "create");
|
"open" : "create");
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
@ -1319,19 +1319,22 @@ os_aio_array_create(
|
||||||
array->n_segments = n_segments;
|
array->n_segments = n_segments;
|
||||||
array->n_reserved = 0;
|
array->n_reserved = 0;
|
||||||
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
|
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
|
||||||
array->events = ut_malloc(n * sizeof(os_event_t));
|
#ifdef __WIN__
|
||||||
|
array->native_events = ut_malloc(n * sizeof(os_native_event_t));
|
||||||
|
#endif
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
slot = os_aio_array_get_nth_slot(array, i);
|
slot = os_aio_array_get_nth_slot(array, i);
|
||||||
|
|
||||||
slot->pos = i;
|
slot->pos = i;
|
||||||
slot->reserved = FALSE;
|
slot->reserved = FALSE;
|
||||||
#ifdef WIN_ASYNC_IO
|
#ifdef WIN_ASYNC_IO
|
||||||
|
slot->event = os_event_create(NULL);
|
||||||
|
|
||||||
over = &(slot->control);
|
over = &(slot->control);
|
||||||
|
|
||||||
over->hEvent = os_event_create(NULL);
|
over->hEvent = slot->event->handle;
|
||||||
|
|
||||||
*((array->events) + i) = over->hEvent;
|
*((array->native_events) + i) = over->hEvent;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,7 +1432,7 @@ os_aio_array_wake_win_aio_at_shutdown(
|
||||||
|
|
||||||
for (i = 0; i < array->n_slots; i++) {
|
for (i = 0; i < array->n_slots; i++) {
|
||||||
|
|
||||||
os_event_set(*(array->events + i));
|
os_event_set((array->slots + i)->event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1689,7 +1692,7 @@ loop:
|
||||||
control = &(slot->control);
|
control = &(slot->control);
|
||||||
control->Offset = (DWORD)offset;
|
control->Offset = (DWORD)offset;
|
||||||
control->OffsetHigh = (DWORD)offset_high;
|
control->OffsetHigh = (DWORD)offset_high;
|
||||||
os_event_reset(control->hEvent);
|
os_event_reset(slot->event);
|
||||||
|
|
||||||
#elif defined(POSIX_ASYNC_IO)
|
#elif defined(POSIX_ASYNC_IO)
|
||||||
|
|
||||||
|
@ -1747,7 +1750,7 @@ os_aio_array_free_slot(
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN_ASYNC_IO
|
#ifdef WIN_ASYNC_IO
|
||||||
os_event_reset(slot->control.hEvent);
|
os_event_reset(slot->event);
|
||||||
#endif
|
#endif
|
||||||
os_mutex_exit(array->mutex);
|
os_mutex_exit(array->mutex);
|
||||||
}
|
}
|
||||||
|
@ -1916,7 +1919,8 @@ os_aio(
|
||||||
wait in the Windows case. */
|
wait in the Windows case. */
|
||||||
|
|
||||||
if (type == OS_FILE_READ) {
|
if (type == OS_FILE_READ) {
|
||||||
return(os_file_read(file, buf, offset, offset_high, n));
|
return(os_file_read(file, buf, offset,
|
||||||
|
offset_high, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(type == OS_FILE_WRITE);
|
ut_a(type == OS_FILE_WRITE);
|
||||||
|
@ -1995,7 +1999,6 @@ try_again:
|
||||||
if (os_aio_use_native_aio) {
|
if (os_aio_use_native_aio) {
|
||||||
if ((ret && len == n)
|
if ((ret && len == n)
|
||||||
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|
||||||
|
|
||||||
/* aio was queued successfully! */
|
/* aio was queued successfully! */
|
||||||
|
|
||||||
if (mode == OS_AIO_SYNC) {
|
if (mode == OS_AIO_SYNC) {
|
||||||
|
@ -2025,8 +2028,8 @@ try_again:
|
||||||
|
|
||||||
os_aio_array_free_slot(array, slot);
|
os_aio_array_free_slot(array, slot);
|
||||||
|
|
||||||
retry = os_file_handle_error(file, name, "aio");
|
retry = os_file_handle_error(file, name,
|
||||||
|
type == OS_FILE_READ ? "aio read" : "aio write");
|
||||||
if (retry) {
|
if (retry) {
|
||||||
|
|
||||||
goto try_again;
|
goto try_again;
|
||||||
|
@ -2091,15 +2094,15 @@ os_aio_windows_handle(
|
||||||
n = array->n_slots / array->n_segments;
|
n = array->n_slots / array->n_segments;
|
||||||
|
|
||||||
if (array == os_aio_sync_array) {
|
if (array == os_aio_sync_array) {
|
||||||
srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page";
|
srv_io_thread_op_info[orig_seg] =
|
||||||
|
"wait Windows aio for 1 page";
|
||||||
ut_ad(pos < array->n_slots);
|
os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
|
||||||
os_event_wait(array->events[pos]);
|
|
||||||
i = pos;
|
i = pos;
|
||||||
} else {
|
} else {
|
||||||
srv_io_thread_op_info[orig_seg] =
|
srv_io_thread_op_info[orig_seg] =
|
||||||
"wait Windows aio";
|
"wait Windows aio";
|
||||||
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
i = os_event_wait_multiple(n,
|
||||||
|
(array->native_events) + segment * n);
|
||||||
}
|
}
|
||||||
|
|
||||||
os_mutex_enter(array->mutex);
|
os_mutex_enter(array->mutex);
|
||||||
|
@ -2124,7 +2127,7 @@ os_aio_windows_handle(
|
||||||
ut_a(TRUE == os_file_flush(slot->file));
|
ut_a(TRUE == os_file_flush(slot->file));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
os_file_handle_error(slot->file, slot->name, "aio");
|
os_file_handle_error(slot->file, slot->name, "Windows aio");
|
||||||
|
|
||||||
ret_val = FALSE;
|
ret_val = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,7 @@ struct os_mutex_struct{
|
||||||
/* list of all 'slow' OS mutexes created */
|
/* list of all 'slow' OS mutexes created */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mutex protecting the thread count and the lists of OS mutexes
|
/* Mutex protecting counts and the lists of OS mutexes and events */
|
||||||
and events */
|
|
||||||
os_mutex_t os_sync_mutex;
|
os_mutex_t os_sync_mutex;
|
||||||
ibool os_sync_mutex_inited = FALSE;
|
ibool os_sync_mutex_inited = FALSE;
|
||||||
|
|
||||||
|
@ -41,15 +40,15 @@ ibool os_sync_mutex_inited = FALSE;
|
||||||
os_thread_exit */
|
os_thread_exit */
|
||||||
ulint os_thread_count = 0;
|
ulint os_thread_count = 0;
|
||||||
|
|
||||||
/* The list of all events created (not in Windows) */
|
/* The list of all events created */
|
||||||
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
|
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
|
||||||
|
|
||||||
/* The list of all OS 'slow' mutexes */
|
/* The list of all OS 'slow' mutexes */
|
||||||
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
|
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
|
||||||
|
|
||||||
/* The following are approximate counters for debugging in Unix */
|
|
||||||
ulint os_event_count = 0;
|
ulint os_event_count = 0;
|
||||||
ulint os_mutex_count = 0;
|
ulint os_mutex_count = 0;
|
||||||
|
ulint os_fast_mutex_count = 0;
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
|
@ -68,7 +67,7 @@ os_sync_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Frees created events (not in Windows) and OS 'slow' mutexes. */
|
Frees created events and OS 'slow' mutexes. */
|
||||||
|
|
||||||
void
|
void
|
||||||
os_sync_free(void)
|
os_sync_free(void)
|
||||||
|
@ -89,6 +88,12 @@ os_sync_free(void)
|
||||||
mutex = UT_LIST_GET_FIRST(os_mutex_list);
|
mutex = UT_LIST_GET_FIRST(os_mutex_list);
|
||||||
|
|
||||||
while (mutex) {
|
while (mutex) {
|
||||||
|
if (mutex == os_sync_mutex) {
|
||||||
|
/* Set the flag to FALSE so that we do not try to
|
||||||
|
reserve os_sync_mutex any more in remaining freeing
|
||||||
|
operations in shutdown */
|
||||||
|
os_sync_mutex_inited = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
os_mutex_free(mutex);
|
os_mutex_free(mutex);
|
||||||
|
|
||||||
|
@ -97,10 +102,9 @@ os_sync_free(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Creates an event semaphore, i.e., a semaphore which may
|
Creates an event semaphore, i.e., a semaphore which may just have two
|
||||||
just have two states: signaled and nonsignaled.
|
states: signaled and nonsignaled. The created event is manual reset: it
|
||||||
The created event is manual reset: it must be reset
|
must be reset explicitly by calling sync_os_reset_event. */
|
||||||
explicitly by calling sync_os_reset_event. */
|
|
||||||
|
|
||||||
os_event_t
|
os_event_t
|
||||||
os_event_create(
|
os_event_create(
|
||||||
|
@ -112,20 +116,18 @@ os_event_create(
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
os_event_t event;
|
os_event_t event;
|
||||||
|
|
||||||
event = CreateEvent(NULL, /* No security attributes */
|
event = ut_malloc(sizeof(struct os_event_struct));
|
||||||
|
|
||||||
|
event->handle = CreateEvent(NULL,/* No security attributes */
|
||||||
TRUE, /* Manual reset */
|
TRUE, /* Manual reset */
|
||||||
FALSE, /* Initial state nonsignaled */
|
FALSE, /* Initial state nonsignaled */
|
||||||
name);
|
name);
|
||||||
if (!event) {
|
if (!event->handle) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
|
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
|
||||||
(ulint)GetLastError());
|
(ulint)GetLastError());
|
||||||
}
|
}
|
||||||
|
#else /* Unix */
|
||||||
ut_a(event);
|
|
||||||
|
|
||||||
return(event);
|
|
||||||
#else
|
|
||||||
os_event_t event;
|
os_event_t event;
|
||||||
|
|
||||||
UT_NOT_USED(name);
|
UT_NOT_USED(name);
|
||||||
|
@ -141,7 +143,9 @@ os_event_create(
|
||||||
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
|
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
|
||||||
#endif
|
#endif
|
||||||
event->is_set = FALSE;
|
event->is_set = FALSE;
|
||||||
|
#endif /* __WIN__ */
|
||||||
|
|
||||||
|
/* Put to the list of events */
|
||||||
os_mutex_enter(os_sync_mutex);
|
os_mutex_enter(os_sync_mutex);
|
||||||
|
|
||||||
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
|
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
|
||||||
|
@ -151,13 +155,12 @@ os_event_create(
|
||||||
os_mutex_exit(os_sync_mutex);
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
|
||||||
return(event);
|
return(event);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Creates an auto-reset event semaphore, i.e., an event
|
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
||||||
which is automatically reset when a single thread is
|
reset when a single thread is released. Works only in Windows. */
|
||||||
released. */
|
|
||||||
|
|
||||||
os_event_t
|
os_event_t
|
||||||
os_event_create_auto(
|
os_event_create_auto(
|
||||||
|
@ -166,26 +169,33 @@ os_event_create_auto(
|
||||||
char* name) /* in: the name of the event, if NULL
|
char* name) /* in: the name of the event, if NULL
|
||||||
the event is created without a name */
|
the event is created without a name */
|
||||||
{
|
{
|
||||||
#ifdef __WIN__
|
|
||||||
os_event_t event;
|
os_event_t event;
|
||||||
|
|
||||||
event = CreateEvent(NULL, /* No security attributes */
|
event = ut_malloc(sizeof(struct os_event_struct));
|
||||||
|
|
||||||
|
event->handle = CreateEvent(NULL,/* No security attributes */
|
||||||
FALSE, /* Auto-reset */
|
FALSE, /* Auto-reset */
|
||||||
FALSE, /* Initial state nonsignaled */
|
FALSE, /* Initial state nonsignaled */
|
||||||
name);
|
name);
|
||||||
ut_a(event);
|
|
||||||
|
if (!event->handle) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n",
|
||||||
|
(ulint)GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put to the list of events */
|
||||||
|
os_mutex_enter(os_sync_mutex);
|
||||||
|
|
||||||
|
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
|
||||||
|
|
||||||
|
os_event_count++;
|
||||||
|
|
||||||
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
|
||||||
return(event);
|
return(event);
|
||||||
#else
|
|
||||||
/* Does nothing in Posix because we do not need this with MySQL */
|
|
||||||
|
|
||||||
UT_NOT_USED(name);
|
|
||||||
|
|
||||||
ut_a(0);
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
Sets an event semaphore to the signaled state: lets waiting threads
|
Sets an event semaphore to the signaled state: lets waiting threads
|
||||||
|
@ -198,7 +208,7 @@ os_event_set(
|
||||||
{
|
{
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
ut_a(SetEvent(event));
|
ut_a(SetEvent(event->handle));
|
||||||
#else
|
#else
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
|
@ -227,7 +237,7 @@ os_event_reset(
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
ut_a(ResetEvent(event));
|
ut_a(ResetEvent(event->handle));
|
||||||
#else
|
#else
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
|
@ -255,12 +265,14 @@ os_event_free(
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
ut_a(CloseHandle(event));
|
ut_a(CloseHandle(event->handle));
|
||||||
#else
|
#else
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
os_fast_mutex_free(&(event->os_mutex));
|
os_fast_mutex_free(&(event->os_mutex));
|
||||||
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
|
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
|
||||||
|
#endif
|
||||||
|
/* Remove from the list of events */
|
||||||
|
|
||||||
os_mutex_enter(os_sync_mutex);
|
os_mutex_enter(os_sync_mutex);
|
||||||
|
|
||||||
|
@ -271,7 +283,6 @@ os_event_free(
|
||||||
os_mutex_exit(os_sync_mutex);
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
|
||||||
ut_free(event);
|
ut_free(event);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
|
@ -291,7 +302,7 @@ os_event_wait(
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
/* Specify an infinite time limit for waiting */
|
/* Specify an infinite time limit for waiting */
|
||||||
err = WaitForSingleObject(event, INFINITE);
|
err = WaitForSingleObject(event->handle, INFINITE);
|
||||||
|
|
||||||
ut_a(err == WAIT_OBJECT_0);
|
ut_a(err == WAIT_OBJECT_0);
|
||||||
|
|
||||||
|
@ -324,7 +335,7 @@ loop:
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
Waits for an event object until it is in the signaled state or
|
Waits for an event object until it is in the signaled state or
|
||||||
a timeout is exceeded. */
|
a timeout is exceeded. In Unix the timeout is always infinite. */
|
||||||
|
|
||||||
ulint
|
ulint
|
||||||
os_event_wait_time(
|
os_event_wait_time(
|
||||||
|
@ -341,9 +352,9 @@ os_event_wait_time(
|
||||||
ut_a(event);
|
ut_a(event);
|
||||||
|
|
||||||
if (time != OS_SYNC_INFINITE_TIME) {
|
if (time != OS_SYNC_INFINITE_TIME) {
|
||||||
err = WaitForSingleObject(event, time / 1000);
|
err = WaitForSingleObject(event->handle, time / 1000);
|
||||||
} else {
|
} else {
|
||||||
err = WaitForSingleObject(event, INFINITE);
|
err = WaitForSingleObject(event->handle, INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == WAIT_OBJECT_0) {
|
if (err == WAIT_OBJECT_0) {
|
||||||
|
@ -367,8 +378,9 @@ os_event_wait_time(
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
Waits for any event in an event array. Returns if even a single
|
Waits for any event in an OS native event array. Returns if even a single
|
||||||
one is signaled or becomes signaled. */
|
one is signaled or becomes signaled. */
|
||||||
|
|
||||||
ulint
|
ulint
|
||||||
|
@ -378,16 +390,16 @@ os_event_wait_multiple(
|
||||||
which was signaled */
|
which was signaled */
|
||||||
ulint n, /* in: number of events in the
|
ulint n, /* in: number of events in the
|
||||||
array */
|
array */
|
||||||
os_event_t* event_array) /* in: pointer to an array of event
|
os_native_event_t* native_event_array)
|
||||||
|
/* in: pointer to an array of event
|
||||||
handles */
|
handles */
|
||||||
{
|
{
|
||||||
#ifdef __WIN__
|
|
||||||
DWORD index;
|
DWORD index;
|
||||||
|
|
||||||
ut_a(event_array);
|
ut_a(native_event_array);
|
||||||
ut_a(n > 0);
|
ut_a(n > 0);
|
||||||
|
|
||||||
index = WaitForMultipleObjects(n, event_array,
|
index = WaitForMultipleObjects(n, native_event_array,
|
||||||
FALSE, /* Wait for any 1 event */
|
FALSE, /* Wait for any 1 event */
|
||||||
INFINITE); /* Infinite wait time
|
INFINITE); /* Infinite wait time
|
||||||
limit */
|
limit */
|
||||||
|
@ -399,21 +411,12 @@ os_event_wait_multiple(
|
||||||
}
|
}
|
||||||
|
|
||||||
return(index - WAIT_OBJECT_0);
|
return(index - WAIT_OBJECT_0);
|
||||||
#else
|
|
||||||
ut_a(n == 0);
|
|
||||||
|
|
||||||
/* In Posix we can only wait for a single event */
|
|
||||||
|
|
||||||
os_event_wait(*event_array);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
Creates an operating system mutex semaphore.
|
Creates an operating system mutex semaphore. Because these are slow, the
|
||||||
Because these are slow, the mutex semaphore of the database
|
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
||||||
itself (sync_mutex_t) should be used where possible. */
|
|
||||||
|
|
||||||
os_mutex_t
|
os_mutex_t
|
||||||
os_mutex_create(
|
os_mutex_create(
|
||||||
|
@ -430,50 +433,35 @@ os_mutex_create(
|
||||||
FALSE, /* Initial state: no owner */
|
FALSE, /* Initial state: no owner */
|
||||||
name);
|
name);
|
||||||
ut_a(mutex);
|
ut_a(mutex);
|
||||||
|
#else
|
||||||
|
os_fast_mutex_t* mutex;
|
||||||
|
os_mutex_t mutex_str;
|
||||||
|
|
||||||
|
UT_NOT_USED(name);
|
||||||
|
|
||||||
|
mutex = ut_malloc(sizeof(os_fast_mutex_t));
|
||||||
|
|
||||||
|
os_fast_mutex_init(mutex);
|
||||||
|
#endif
|
||||||
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
||||||
|
|
||||||
mutex_str->handle = mutex;
|
mutex_str->handle = mutex;
|
||||||
mutex_str->count = 0;
|
mutex_str->count = 0;
|
||||||
|
|
||||||
if (os_sync_mutex_inited) {
|
if (os_sync_mutex_inited) {
|
||||||
|
/* When creating os_sync_mutex itself we cannot reserve it */
|
||||||
os_mutex_enter(os_sync_mutex);
|
os_mutex_enter(os_sync_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
|
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
|
||||||
|
|
||||||
|
os_mutex_count++;
|
||||||
|
|
||||||
if (os_sync_mutex_inited) {
|
if (os_sync_mutex_inited) {
|
||||||
os_mutex_exit(os_sync_mutex);
|
os_mutex_exit(os_sync_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(mutex_str);
|
return(mutex_str);
|
||||||
#else
|
|
||||||
os_fast_mutex_t* os_mutex;
|
|
||||||
os_mutex_t mutex_str;
|
|
||||||
|
|
||||||
UT_NOT_USED(name);
|
|
||||||
|
|
||||||
os_mutex = ut_malloc(sizeof(os_fast_mutex_t));
|
|
||||||
|
|
||||||
os_fast_mutex_init(os_mutex);
|
|
||||||
|
|
||||||
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
|
||||||
|
|
||||||
mutex_str->handle = os_mutex;
|
|
||||||
mutex_str->count = 0;
|
|
||||||
|
|
||||||
if (os_sync_mutex_inited) {
|
|
||||||
os_mutex_enter(os_sync_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
|
|
||||||
|
|
||||||
if (os_sync_mutex_inited) {
|
|
||||||
os_mutex_exit(os_sync_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(mutex_str);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
|
@ -513,21 +501,14 @@ os_mutex_exit(
|
||||||
/*==========*/
|
/*==========*/
|
||||||
os_mutex_t mutex) /* in: mutex to release */
|
os_mutex_t mutex) /* in: mutex to release */
|
||||||
{
|
{
|
||||||
#ifdef __WIN__
|
|
||||||
ut_a(mutex);
|
ut_a(mutex);
|
||||||
|
|
||||||
ut_a(mutex->count == 1);
|
ut_a(mutex->count == 1);
|
||||||
|
|
||||||
(mutex->count)--;
|
(mutex->count)--;
|
||||||
|
#ifdef __WIN__
|
||||||
ut_a(ReleaseMutex(mutex->handle));
|
ut_a(ReleaseMutex(mutex->handle));
|
||||||
#else
|
#else
|
||||||
ut_a(mutex);
|
|
||||||
|
|
||||||
ut_a(mutex->count == 1);
|
|
||||||
|
|
||||||
(mutex->count)--;
|
|
||||||
|
|
||||||
os_fast_mutex_unlock(mutex->handle);
|
os_fast_mutex_unlock(mutex->handle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -540,25 +521,25 @@ os_mutex_free(
|
||||||
/*==========*/
|
/*==========*/
|
||||||
os_mutex_t mutex) /* in: mutex to free */
|
os_mutex_t mutex) /* in: mutex to free */
|
||||||
{
|
{
|
||||||
#ifdef __WIN__
|
|
||||||
ut_a(mutex);
|
ut_a(mutex);
|
||||||
|
|
||||||
|
if (os_sync_mutex_inited) {
|
||||||
os_mutex_enter(os_sync_mutex);
|
os_mutex_enter(os_sync_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
|
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
|
||||||
|
|
||||||
os_mutex_exit(os_sync_mutex);
|
os_mutex_count--;
|
||||||
|
|
||||||
|
if (os_sync_mutex_inited) {
|
||||||
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
ut_a(CloseHandle(mutex->handle));
|
ut_a(CloseHandle(mutex->handle));
|
||||||
|
|
||||||
ut_free(mutex);
|
ut_free(mutex);
|
||||||
#else
|
#else
|
||||||
os_mutex_enter(os_sync_mutex);
|
|
||||||
|
|
||||||
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
|
|
||||||
|
|
||||||
os_mutex_exit(os_sync_mutex);
|
|
||||||
|
|
||||||
os_fast_mutex_free(mutex->handle);
|
os_fast_mutex_free(mutex->handle);
|
||||||
ut_free(mutex->handle);
|
ut_free(mutex->handle);
|
||||||
ut_free(mutex);
|
ut_free(mutex);
|
||||||
|
@ -583,8 +564,19 @@ os_fast_mutex_init(
|
||||||
#else
|
#else
|
||||||
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
|
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
|
||||||
#endif
|
#endif
|
||||||
os_mutex_count++;
|
|
||||||
#endif
|
#endif
|
||||||
|
if (os_sync_mutex_inited) {
|
||||||
|
/* When creating os_sync_mutex itself (in Unix) we cannot
|
||||||
|
reserve it */
|
||||||
|
|
||||||
|
os_mutex_enter(os_sync_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_fast_mutex_count++;
|
||||||
|
|
||||||
|
if (os_sync_mutex_inited) {
|
||||||
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
|
@ -631,6 +623,17 @@ os_fast_mutex_free(
|
||||||
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
|
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
|
||||||
#else
|
#else
|
||||||
ut_a(0 == pthread_mutex_destroy(fast_mutex));
|
ut_a(0 == pthread_mutex_destroy(fast_mutex));
|
||||||
os_mutex_count--;
|
|
||||||
#endif
|
#endif
|
||||||
|
if (os_sync_mutex_inited) {
|
||||||
|
/* When freeing the last mutexes, we have
|
||||||
|
already freed os_sync_mutex */
|
||||||
|
|
||||||
|
os_mutex_enter(os_sync_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_fast_mutex_count--;
|
||||||
|
|
||||||
|
if (os_sync_mutex_inited) {
|
||||||
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,10 @@ os_thread_exit(
|
||||||
void* exit_value) /* in: exit value; in Windows this void*
|
void* exit_value) /* in: exit value; in Windows this void*
|
||||||
is cast as a DWORD */
|
is cast as a DWORD */
|
||||||
{
|
{
|
||||||
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
|
printf("A thread exits.\n");
|
||||||
|
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||||
|
#endif
|
||||||
os_mutex_enter(os_sync_mutex);
|
os_mutex_enter(os_sync_mutex);
|
||||||
os_thread_count--;
|
os_thread_count--;
|
||||||
os_mutex_exit(os_sync_mutex);
|
os_mutex_exit(os_sync_mutex);
|
||||||
|
|
|
@ -868,6 +868,7 @@ srv_release_max_if_no_queries(void)
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef notdefined
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Releases one utility thread if no queries are active and
|
Releases one utility thread if no queries are active and
|
||||||
the high-water mark 2 for the utility is exceeded. */
|
the high-water mark 2 for the utility is exceeded. */
|
||||||
|
@ -902,7 +903,6 @@ srv_release_one_if_no_queries(void)
|
||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef notdefined
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Decrements the utility meter by the value given and suspends the calling
|
Decrements the utility meter by the value given and suspends the calling
|
||||||
thread, which must be an utility thread of the type given, if necessary. */
|
thread, which must be an utility thread of the type given, if necessary. */
|
||||||
|
@ -1013,6 +1013,8 @@ srv_communication_init(
|
||||||
ut_a(ret == 0);
|
ut_a(ret == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef notdefined
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Implements the recovery utility. */
|
Implements the recovery utility. */
|
||||||
static
|
static
|
||||||
|
@ -1072,6 +1074,7 @@ srv_purge_thread(
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
#endif /* notdefined */
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Creates the utility threads. */
|
Creates the utility threads. */
|
||||||
|
@ -1102,6 +1105,7 @@ srv_create_utility_threads(void)
|
||||||
ut_a(thread); */
|
ut_a(thread); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef notdefined
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Implements the communication threads. */
|
Implements the communication threads. */
|
||||||
static
|
static
|
||||||
|
@ -1151,6 +1155,7 @@ srv_com_thread(
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Creates the communication threads. */
|
Creates the communication threads. */
|
||||||
|
@ -1171,6 +1176,7 @@ srv_create_com_threads(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef notdefined
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Implements the worker threads. */
|
Implements the worker threads. */
|
||||||
static
|
static
|
||||||
|
@ -1215,6 +1221,7 @@ srv_worker_thread(
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Creates the worker threads. */
|
Creates the worker threads. */
|
||||||
|
@ -2490,6 +2497,10 @@ srv_lock_timeout_and_monitor_thread(
|
||||||
char* buf;
|
char* buf;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
|
printf("Lock timeout thread starts\n");
|
||||||
|
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||||
|
#endif
|
||||||
UT_NOT_USED(arg);
|
UT_NOT_USED(arg);
|
||||||
srv_last_monitor_time = time(NULL);
|
srv_last_monitor_time = time(NULL);
|
||||||
last_table_monitor_time = time(NULL);
|
last_table_monitor_time = time(NULL);
|
||||||
|
@ -2630,6 +2641,10 @@ loop:
|
||||||
exit_func:
|
exit_func:
|
||||||
srv_lock_timeout_and_monitor_active = FALSE;
|
srv_lock_timeout_and_monitor_active = FALSE;
|
||||||
|
|
||||||
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
|
thread should always use that to exit and not use return() to exit. */
|
||||||
|
|
||||||
|
os_thread_exit(NULL);
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
return(NULL);
|
return(NULL);
|
||||||
#else
|
#else
|
||||||
|
@ -2655,6 +2670,10 @@ srv_error_monitor_thread(
|
||||||
ulint cnt = 0;
|
ulint cnt = 0;
|
||||||
|
|
||||||
UT_NOT_USED(arg);
|
UT_NOT_USED(arg);
|
||||||
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
|
printf("Error monitor thread starts\n");
|
||||||
|
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||||
|
#endif
|
||||||
loop:
|
loop:
|
||||||
srv_error_monitor_active = TRUE;
|
srv_error_monitor_active = TRUE;
|
||||||
|
|
||||||
|
@ -2691,6 +2710,9 @@ loop:
|
||||||
|
|
||||||
srv_error_monitor_active = FALSE;
|
srv_error_monitor_active = FALSE;
|
||||||
|
|
||||||
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
|
thread should always use that to exit and not use return() to exit. */
|
||||||
|
|
||||||
os_thread_exit(NULL);
|
os_thread_exit(NULL);
|
||||||
|
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
|
@ -2771,6 +2793,10 @@ srv_master_thread(
|
||||||
|
|
||||||
UT_NOT_USED(arg);
|
UT_NOT_USED(arg);
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
|
printf("Master thread starts\n");
|
||||||
|
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||||
|
#endif
|
||||||
srv_main_thread_process_no = os_proc_get_number();
|
srv_main_thread_process_no = os_proc_get_number();
|
||||||
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
|
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
|
||||||
|
|
||||||
|
@ -3006,6 +3032,15 @@ background_loop:
|
||||||
|
|
||||||
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
|
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
|
||||||
|
|
||||||
|
if (n_tables_to_drop > 0) {
|
||||||
|
/* Do not monopolize the CPU even if there are tables waiting
|
||||||
|
in the background drop queue. (It is essentially a bug if
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
srv_main_thread_op_info = (char*)"purging";
|
srv_main_thread_op_info = (char*)"purging";
|
||||||
|
|
||||||
if (srv_fast_shutdown && srv_shutdown_state > 0) {
|
if (srv_fast_shutdown && srv_shutdown_state > 0) {
|
||||||
|
@ -3144,6 +3179,13 @@ suspend_thread:
|
||||||
|
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
|
thread should always use that to exit and not use return() to exit.
|
||||||
|
The thread actually never comes here because it is exited in an
|
||||||
|
os_event_wait(). */
|
||||||
|
|
||||||
|
os_thread_exit(NULL);
|
||||||
|
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
return(NULL);
|
return(NULL);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -414,8 +414,10 @@ io_handler_thread(
|
||||||
|
|
||||||
segment = *((ulint*)arg);
|
segment = *((ulint*)arg);
|
||||||
|
|
||||||
/* printf("Io handler thread %lu starts\n", segment); */
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
|
printf("Io handler thread %lu starts\n", segment);
|
||||||
|
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||||
|
#endif
|
||||||
for (i = 0;; i++) {
|
for (i = 0;; i++) {
|
||||||
fil_aio_wait(segment);
|
fil_aio_wait(segment);
|
||||||
|
|
||||||
|
@ -424,6 +426,13 @@ io_handler_thread(
|
||||||
mutex_exit(&ios_mutex);
|
mutex_exit(&ios_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
|
thread should always use that to exit and not use return() to exit.
|
||||||
|
The thread actually never comes here because it is exited in an
|
||||||
|
os_event_wait(). */
|
||||||
|
|
||||||
|
os_thread_exit(NULL);
|
||||||
|
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
return(NULL);
|
return(NULL);
|
||||||
#else
|
#else
|
||||||
|
@ -1585,21 +1594,32 @@ innobase_shutdown_for_mysql(void)
|
||||||
os_thread_count);
|
os_thread_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. Free all InnoDB's own mutexes */
|
/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
|
||||||
|
them */
|
||||||
|
|
||||||
sync_close();
|
sync_close();
|
||||||
|
|
||||||
/* 4. Free all OS synchronization primitives (in Windows currently
|
/* 4. Free the os_conc_mutex and all os_events and os_mutexes */
|
||||||
events are not freed) */
|
|
||||||
|
|
||||||
srv_free();
|
srv_free();
|
||||||
os_sync_free();
|
os_sync_free();
|
||||||
|
|
||||||
/* 5. Free all allocated memory (and the os_fast_mutex created in
|
/* 5. Free all allocated memory and the os_fast_mutex created in
|
||||||
ut0mem.c */
|
ut0mem.c */
|
||||||
|
|
||||||
ut_free_all_mem();
|
ut_free_all_mem();
|
||||||
|
|
||||||
|
if (os_thread_count != 0
|
||||||
|
|| os_event_count != 0
|
||||||
|
|| os_mutex_count != 0
|
||||||
|
|| os_fast_mutex_count != 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
|
||||||
|
"InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
|
||||||
|
os_thread_count, os_event_count, os_mutex_count,
|
||||||
|
os_fast_mutex_count);
|
||||||
|
}
|
||||||
|
|
||||||
if (srv_print_verbose_log) {
|
if (srv_print_verbose_log) {
|
||||||
ut_print_timestamp(stderr);
|
ut_print_timestamp(stderr);
|
||||||
fprintf(stderr, " InnoDB: Shutdown completed\n");
|
fprintf(stderr, " InnoDB: Shutdown completed\n");
|
||||||
|
|
|
@ -64,7 +64,7 @@ concat_ws(NULL,'a') concat_ws(',',NULL,'')
|
||||||
NULL
|
NULL
|
||||||
select concat_ws(',','',NULL,'a');
|
select concat_ws(',','',NULL,'a');
|
||||||
concat_ws(',','',NULL,'a')
|
concat_ws(',','',NULL,'a')
|
||||||
a
|
,a
|
||||||
SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"');
|
SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"');
|
||||||
CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"')
|
CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"')
|
||||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
||||||
|
|
|
@ -22,3 +22,9 @@ day id category name
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
drop table t3;
|
drop table t3;
|
||||||
|
create table t1(a int, b int, unique(b));
|
||||||
|
insert into t1 values(1,10);
|
||||||
|
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
|
||||||
|
show status like 'slave_running';
|
||||||
|
Variable_name Value
|
||||||
|
Slave_running OFF
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#
|
#
|
||||||
# check replication of load data for temporary tables with additional parameters
|
# check replication of load data for temporary tables with additional parameters
|
||||||
#
|
#
|
||||||
|
# check if duplicate entries trigger an error (they should unless IGNORE or
|
||||||
|
# REPLACE was used on the master) (bug 571).
|
||||||
|
|
||||||
source include/master-slave.inc;
|
source include/master-slave.inc;
|
||||||
|
|
||||||
create table t1(a int not null auto_increment, b int, primary key(a) );
|
create table t1(a int not null auto_increment, b int, primary key(a) );
|
||||||
|
@ -27,7 +30,21 @@ connection master;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
drop table t3;
|
drop table t3;
|
||||||
|
create table t1(a int, b int, unique(b));
|
||||||
|
|
||||||
save_master_pos;
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sync_with_master;
|
sync_with_master;
|
||||||
|
insert into t1 values(1,10);
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
|
||||||
|
|
||||||
|
save_master_pos;
|
||||||
|
connection slave;
|
||||||
|
# don't sync_with_master because the slave SQL thread should be stopped because
|
||||||
|
# of the error so MASTER_POS_WAIT() will not return; just sleep and hope the
|
||||||
|
# slave SQL thread will have had time to stop.
|
||||||
|
|
||||||
|
sleep 1;
|
||||||
|
show status like 'slave_running';
|
||||||
|
|
|
@ -122,12 +122,24 @@ void init_thr_alarm(uint max_alarms)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Request alarm after sec seconds.
|
Request alarm after sec seconds.
|
||||||
A pointer is returned with points to a non-zero int when the alarm has been
|
|
||||||
given. This can't be called from the alarm-handling thread.
|
SYNOPSIS
|
||||||
Returns 0 if no more alarms are allowed (aborted by process)
|
thr_alarm()
|
||||||
|
alrm Pointer to alarm detection
|
||||||
|
alarm_data Structure to store in alarm queue
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
This function can't be called from the alarm-handling thread.
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
0 ok
|
||||||
|
1 If no more alarms are allowed (aborted by process)
|
||||||
|
|
||||||
|
Stores in first argument a pointer to a non-zero int which is set to 0
|
||||||
|
when the alarm has been given
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
||||||
{
|
{
|
||||||
ulong now;
|
ulong now;
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
|
@ -209,7 +221,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
|
||||||
ALARM *alarm_data;
|
ALARM *alarm_data;
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
uint i;
|
uint i;
|
||||||
bool found=0;
|
my_bool found=0;
|
||||||
DBUG_ENTER("thr_end_alarm");
|
DBUG_ENTER("thr_end_alarm");
|
||||||
|
|
||||||
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
||||||
|
@ -230,10 +242,9 @@ void thr_end_alarm(thr_alarm_t *alarmed)
|
||||||
DBUG_ASSERT(!*alarmed || found);
|
DBUG_ASSERT(!*alarmed || found);
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
#ifdef MAIN
|
if (*alarmed)
|
||||||
printf("Warning: Didn't find alarm %lx in queue of %d alarms\n",
|
fprintf(stderr,"Warning: Didn't find alarm %lx in queue of %d alarms\n",
|
||||||
(long) *alarmed, alarm_queue.elements);
|
(long) *alarmed, alarm_queue.elements);
|
||||||
#endif
|
|
||||||
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
|
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
|
||||||
(long) *alarmed));
|
(long) *alarmed));
|
||||||
}
|
}
|
||||||
|
|
178
sql/ha_innodb.cc
178
sql/ha_innodb.cc
|
@ -131,9 +131,11 @@ static void innobase_print_error(const char* db_errpfx, char* buffer);
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Releases possible search latch and InnoDB thread FIFO ticket. These should
|
Releases possible search latch and InnoDB thread FIFO ticket. These should
|
||||||
be released at each SQL statement end. It does no harm to release these
|
be released at each SQL statement end, and also when mysqld passes the
|
||||||
also in the middle of an SQL statement. */
|
control to the client. It does no harm to release these also in the middle
|
||||||
|
of an SQL statement. */
|
||||||
static
|
static
|
||||||
|
inline
|
||||||
void
|
void
|
||||||
innobase_release_stat_resources(
|
innobase_release_stat_resources(
|
||||||
/*============================*/
|
/*============================*/
|
||||||
|
@ -914,6 +916,11 @@ innobase_commit_low(
|
||||||
trx_t* trx) /* in: transaction handle */
|
trx_t* trx) /* in: transaction handle */
|
||||||
{
|
{
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
|
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Guilhem should check if master_log_name, pending
|
/* TODO: Guilhem should check if master_log_name, pending
|
||||||
etc. are right if the master log gets rotated! Possible bug here.
|
etc. are right if the master log gets rotated! Possible bug here.
|
||||||
Comment by Heikki March 4, 2003. */
|
Comment by Heikki March 4, 2003. */
|
||||||
|
@ -929,11 +936,13 @@ innobase_commit_low(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
#endif /* HAVE_REPLICATION */
|
#endif /* HAVE_REPLICATION */
|
||||||
|
|
||||||
trx_commit_for_mysql(trx);
|
trx_commit_for_mysql(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Commits a transaction in an InnoDB database. */
|
Commits a transaction in an InnoDB database or marks an SQL statement
|
||||||
|
ended. */
|
||||||
|
|
||||||
int
|
int
|
||||||
innobase_commit(
|
innobase_commit(
|
||||||
|
@ -951,29 +960,45 @@ innobase_commit(
|
||||||
DBUG_ENTER("innobase_commit");
|
DBUG_ENTER("innobase_commit");
|
||||||
DBUG_PRINT("trans", ("ending transaction"));
|
DBUG_PRINT("trans", ("ending transaction"));
|
||||||
|
|
||||||
|
/* The flag thd->transaction.all.innodb_active_trans is set to 1
|
||||||
|
in ::external_lock and ::start_stmt, and it is only set to 0 in
|
||||||
|
a commit or a rollback. If it is 0 we know there cannot be resources
|
||||||
|
to be freed and we can return immediately. */
|
||||||
|
|
||||||
|
if (thd->transaction.all.innodb_active_trans == 0) {
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
trx = check_trx_exists(thd);
|
trx = check_trx_exists(thd);
|
||||||
|
|
||||||
if (trx->auto_inc_lock) {
|
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle
|
||||||
|
|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
|
||||||
|
|
||||||
/* If we had reserved the auto-inc lock for
|
innobase_commit_low(trx);
|
||||||
some table in this SQL statement, we release it now */
|
|
||||||
|
thd->transaction.all.innodb_active_trans = 0;
|
||||||
|
} else {
|
||||||
|
if (trx->auto_inc_lock) {
|
||||||
|
/* If we had reserved the auto-inc lock for some
|
||||||
|
table in this SQL statement we release it now */
|
||||||
|
|
||||||
srv_conc_enter_innodb(trx);
|
srv_conc_enter_innodb(trx);
|
||||||
row_unlock_table_autoinc_for_mysql(trx);
|
row_unlock_table_autoinc_for_mysql(trx);
|
||||||
srv_conc_exit_innodb(trx);
|
srv_conc_exit_innodb(trx);
|
||||||
}
|
}
|
||||||
|
/* Store the current undo_no of the transaction so that we
|
||||||
|
know where to roll back if we have to roll back the next
|
||||||
|
SQL statement */
|
||||||
|
|
||||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
trx_mark_sql_stat_end(trx);
|
||||||
innobase_commit_low(trx);
|
|
||||||
thd->transaction.all.innodb_active_trans=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release possible statement level resources */
|
/* Release a possible FIFO ticket and search latch */
|
||||||
innobase_release_stat_resources(trx);
|
innobase_release_stat_resources(trx);
|
||||||
trx_mark_sql_stat_end(trx);
|
|
||||||
|
|
||||||
/* Tell InnoDB server that there might be work for
|
/* Tell the InnoDB server that there might be work for utility
|
||||||
utility threads: */
|
threads: */
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
srv_active_wake_master_thread();
|
||||||
|
|
||||||
|
@ -1044,7 +1069,7 @@ innobase_commit_complete(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Rolls back a transaction in an InnoDB database. */
|
Rolls back a transaction or the latest SQL statement in an InnoDB database. */
|
||||||
|
|
||||||
int
|
int
|
||||||
innobase_rollback(
|
innobase_rollback(
|
||||||
|
@ -1085,11 +1110,9 @@ innobase_rollback(
|
||||||
|
|
||||||
srv_conc_exit_innodb(trx);
|
srv_conc_exit_innodb(trx);
|
||||||
|
|
||||||
/* Release possible statement level resources */
|
/* Release a possible FIFO ticket and search latch */
|
||||||
innobase_release_stat_resources(trx);
|
innobase_release_stat_resources(trx);
|
||||||
|
|
||||||
trx_mark_sql_stat_end(trx);
|
|
||||||
|
|
||||||
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
|
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3032,6 +3055,8 @@ create_index(
|
||||||
KEY* key;
|
KEY* key;
|
||||||
KEY_PART_INFO* key_part;
|
KEY_PART_INFO* key_part;
|
||||||
ulint ind_type;
|
ulint ind_type;
|
||||||
|
ulint col_type;
|
||||||
|
ulint prefix_len;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
DBUG_ENTER("create_index");
|
DBUG_ENTER("create_index");
|
||||||
|
@ -3059,6 +3084,27 @@ create_index(
|
||||||
for (i = 0; i < n_fields; i++) {
|
for (i = 0; i < n_fields; i++) {
|
||||||
key_part = key->key_part + i;
|
key_part = key->key_part + i;
|
||||||
|
|
||||||
|
if (key_part->length != key_part->field->pack_length()) {
|
||||||
|
prefix_len = key_part->length;
|
||||||
|
|
||||||
|
col_type = get_innobase_type_from_mysql_type(
|
||||||
|
key_part->field);
|
||||||
|
if (col_type == DATA_INT
|
||||||
|
|| col_type == DATA_FLOAT
|
||||||
|
|| col_type == DATA_DOUBLE
|
||||||
|
|| col_type == DATA_DECIMAL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: error: MySQL is trying to create a column prefix index field\n"
|
||||||
|
"InnoDB: on an inappropriate data type %lu. Table name %s, column name %s.\n",
|
||||||
|
col_type, table_name,
|
||||||
|
key_part->field->field_name);
|
||||||
|
|
||||||
|
prefix_len = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prefix_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* We assume all fields should be sorted in ascending
|
/* We assume all fields should be sorted in ascending
|
||||||
order, hence the '0': */
|
order, hence the '0': */
|
||||||
dict_mem_index_add_field(index,
|
dict_mem_index_add_field(index,
|
||||||
|
@ -3600,8 +3646,7 @@ ha_innobase::records_in_range(
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Gives an UPPER BOUND to the number of rows in a table. This is used in
|
Gives an UPPER BOUND to the number of rows in a table. This is used in
|
||||||
filesort.cc and its better if the upper bound hold.
|
filesort.cc. */
|
||||||
*/
|
|
||||||
|
|
||||||
ha_rows
|
ha_rows
|
||||||
ha_innobase::estimate_number_of_rows(void)
|
ha_innobase::estimate_number_of_rows(void)
|
||||||
|
@ -3636,11 +3681,11 @@ ha_innobase::estimate_number_of_rows(void)
|
||||||
|
|
||||||
/* Calculate a minimum length for a clustered index record and from
|
/* Calculate a minimum length for a clustered index record and from
|
||||||
that an upper bound for the number of rows. Since we only calculate
|
that an upper bound for the number of rows. Since we only calculate
|
||||||
new statistics in row0mysql.c when a tablehas grown
|
new statistics in row0mysql.c when a table has grown by a threshold
|
||||||
by a threshold factor, we must add a safety factor 2 in front
|
factor, we must add a safety factor 2 in front of the formula below. */
|
||||||
of the formula below. */
|
|
||||||
|
|
||||||
estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
|
estimate = 2 * local_data_file_length /
|
||||||
|
dict_index_calc_min_rec_len(index);
|
||||||
|
|
||||||
prebuilt->trx->op_info = (char*)"";
|
prebuilt->trx->op_info = (char*)"";
|
||||||
|
|
||||||
|
@ -3667,26 +3712,35 @@ ha_innobase::scan_time()
|
||||||
return((double) (prebuilt->table->stat_clustered_index_size));
|
return((double) (prebuilt->table->stat_clustered_index_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**********************************************************************
|
||||||
Calculate the time it takes to read a set of ranges through and index
|
Calculate the time it takes to read a set of ranges through an index
|
||||||
This enables us to optimise reads for clustered indexes.
|
This enables us to optimise reads for clustered indexes. */
|
||||||
*/
|
|
||||||
|
|
||||||
double ha_innobase::read_time(uint index, uint ranges, ha_rows rows)
|
double
|
||||||
|
ha_innobase::read_time(
|
||||||
|
/*===================*/
|
||||||
|
/* out: estimated time measured in disk seeks */
|
||||||
|
uint index, /* in: key number */
|
||||||
|
uint ranges, /* in: how many ranges */
|
||||||
|
ha_rows rows) /* in: estimated number of rows in the ranges */
|
||||||
{
|
{
|
||||||
ha_rows total_rows;
|
ha_rows total_rows;
|
||||||
double time_for_scan;
|
double time_for_scan;
|
||||||
|
|
||||||
if (index != table->primary_key)
|
if (index != table->primary_key)
|
||||||
return handler::read_time(index, ranges, rows); // Not clustered
|
return handler::read_time(index, ranges, rows); // Not clustered
|
||||||
|
|
||||||
if (rows <= 2)
|
if (rows <= 2)
|
||||||
return (double) rows;
|
return (double) rows;
|
||||||
/*
|
|
||||||
Assume that the read is proportional to scan time for all rows + one
|
/* Assume that the read time is proportional to the scan time for all
|
||||||
seek per range.
|
rows + at most one seek per range. */
|
||||||
*/
|
|
||||||
time_for_scan= scan_time();
|
time_for_scan= scan_time();
|
||||||
|
|
||||||
if ((total_rows= estimate_number_of_rows()) < rows)
|
if ((total_rows= estimate_number_of_rows()) < rows)
|
||||||
return time_for_scan;
|
return time_for_scan;
|
||||||
|
|
||||||
return (ranges + (double) rows / (double) total_rows * time_for_scan);
|
return (ranges + (double) rows / (double) total_rows * time_for_scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4040,10 +4094,10 @@ ha_innobase::reset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Inside LOCK TABLES MySQL will not call external_lock() between SQL
|
MySQL calls this function at the start of each SQL statement. Inside LOCK
|
||||||
statements. It will call this function at the start of each SQL statement.
|
TABLES the ::external_lock method does not work to mark SQL statement
|
||||||
Note also a spacial case: if a temporary table is created inside LOCK
|
borders. Note also a special case: if a temporary table is created inside
|
||||||
TABLES, MySQL has not called external_lock() at all on that table. */
|
LOCK TABLES, MySQL has not called external_lock() at all on that table. */
|
||||||
|
|
||||||
int
|
int
|
||||||
ha_innobase::start_stmt(
|
ha_innobase::start_stmt(
|
||||||
|
@ -4058,8 +4112,14 @@ ha_innobase::start_stmt(
|
||||||
|
|
||||||
trx = prebuilt->trx;
|
trx = prebuilt->trx;
|
||||||
|
|
||||||
|
/* Here we release the search latch and the InnoDB thread FIFO ticket
|
||||||
|
if they were reserved. They should have been released already at the
|
||||||
|
end of the previous statement, but because inside LOCK TABLES the
|
||||||
|
lock count method does not work to mark the end of a SELECT statement,
|
||||||
|
that may not be the case. We MUST release the search latch before an
|
||||||
|
INSERT, for example. */
|
||||||
|
|
||||||
innobase_release_stat_resources(trx);
|
innobase_release_stat_resources(trx);
|
||||||
trx_mark_sql_stat_end(trx);
|
|
||||||
|
|
||||||
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
||||||
&& trx->read_view) {
|
&& trx->read_view) {
|
||||||
|
@ -4083,6 +4143,7 @@ ha_innobase::start_stmt(
|
||||||
prebuilt->select_lock_type = LOCK_X;
|
prebuilt->select_lock_type = LOCK_X;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the MySQL flag to mark that there is an active transaction */
|
||||||
thd->transaction.all.innodb_active_trans = 1;
|
thd->transaction.all.innodb_active_trans = 1;
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -4146,17 +4207,20 @@ ha_innobase::external_lock(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lock_type != F_UNLCK) {
|
if (lock_type != F_UNLCK) {
|
||||||
if (trx->n_mysql_tables_in_use == 0) {
|
/* MySQL is setting a new table lock */
|
||||||
trx_mark_sql_stat_end(trx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Set the MySQL flag to mark that there is an active
|
||||||
|
transaction */
|
||||||
thd->transaction.all.innodb_active_trans = 1;
|
thd->transaction.all.innodb_active_trans = 1;
|
||||||
|
|
||||||
trx->n_mysql_tables_in_use++;
|
trx->n_mysql_tables_in_use++;
|
||||||
prebuilt->mysql_has_locked = TRUE;
|
prebuilt->mysql_has_locked = TRUE;
|
||||||
|
|
||||||
|
if (trx->n_mysql_tables_in_use == 1) {
|
||||||
trx->isolation_level = innobase_map_isolation_level(
|
trx->isolation_level = innobase_map_isolation_level(
|
||||||
(enum_tx_isolation)
|
(enum_tx_isolation)
|
||||||
thd->variables.tx_isolation);
|
thd->variables.tx_isolation);
|
||||||
|
}
|
||||||
|
|
||||||
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
|
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
|
||||||
&& prebuilt->select_lock_type == LOCK_NONE) {
|
&& prebuilt->select_lock_type == LOCK_NONE) {
|
||||||
|
@ -4172,22 +4236,30 @@ ha_innobase::external_lock(
|
||||||
|
|
||||||
trx->mysql_n_tables_locked++;
|
trx->mysql_n_tables_locked++;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MySQL is releasing a table lock */
|
||||||
|
|
||||||
trx->n_mysql_tables_in_use--;
|
trx->n_mysql_tables_in_use--;
|
||||||
prebuilt->mysql_has_locked = FALSE;
|
prebuilt->mysql_has_locked = FALSE;
|
||||||
auto_inc_counter_for_this_stat = 0;
|
auto_inc_counter_for_this_stat = 0;
|
||||||
|
|
||||||
|
/* If the MySQL lock count drops to zero we know that the current SQL
|
||||||
|
statement has ended */
|
||||||
|
|
||||||
if (trx->n_mysql_tables_in_use == 0) {
|
if (trx->n_mysql_tables_in_use == 0) {
|
||||||
|
|
||||||
trx->mysql_n_tables_locked = 0;
|
trx->mysql_n_tables_locked = 0;
|
||||||
|
|
||||||
prebuilt->used_in_HANDLER = FALSE;
|
prebuilt->used_in_HANDLER = FALSE;
|
||||||
|
|
||||||
/* Here we release the search latch and InnoDB
|
if (!(thd->options
|
||||||
thread FIFO ticket if they were reserved. */
|
& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
|
||||||
|
if (thd->transaction.all.innodb_active_trans != 0) {
|
||||||
innobase_release_stat_resources(trx);
|
innobase_commit(thd, trx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
||||||
&& trx->read_view) {
|
&& trx->read_view) {
|
||||||
|
|
||||||
|
@ -4196,13 +4268,12 @@ ha_innobase::external_lock(
|
||||||
|
|
||||||
read_view_close_for_mysql(trx);
|
read_view_close_for_mysql(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(thd->options
|
|
||||||
& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
|
|
||||||
|
|
||||||
innobase_commit(thd, trx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Here we release the search latch and the InnoDB thread FIFO
|
||||||
|
ticket if they were reserved. */
|
||||||
|
|
||||||
|
innobase_release_stat_resources(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
@ -4513,4 +4584,3 @@ ha_innobase::get_auto_increment()
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_INNOBASE_DB */
|
#endif /* HAVE_INNOBASE_DB */
|
||||||
|
|
||||||
|
|
|
@ -218,8 +218,12 @@ void ha_close_connection(THD* thd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is used to commit or rollback a single statement depending
|
This is used to commit or rollback a single statement depending on the value
|
||||||
on the value of error
|
of error. Note that if the autocommit is on, then the following call inside
|
||||||
|
InnoDB will commit or rollback the whole transaction (= the statement). The
|
||||||
|
autocommit mechanism built into InnoDB is based on counting locks, but if
|
||||||
|
the user has used LOCK TABLES then that mechanism does not know to do the
|
||||||
|
commit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_autocommit_or_rollback(THD *thd, int error)
|
int ha_autocommit_or_rollback(THD *thd, int error)
|
||||||
|
|
|
@ -515,18 +515,18 @@ String *Item_func_concat_ws::val_str(String *str)
|
||||||
str->length(0); // QQ; Should be removed
|
str->length(0); // QQ; Should be removed
|
||||||
res=str;
|
res=str;
|
||||||
|
|
||||||
// Skip until non-null and non-empty argument is found.
|
// Skip until non-null argument is found.
|
||||||
// If not, return the empty string
|
// If not, return the empty string
|
||||||
for (i=0; i < arg_count; i++)
|
for (i=0; i < arg_count; i++)
|
||||||
if ((res= args[i]->val_str(str)) && res->length())
|
if ((res= args[i]->val_str(str)))
|
||||||
break;
|
break;
|
||||||
if (i == arg_count)
|
if (i == arg_count)
|
||||||
return &empty_string;
|
return &empty_string;
|
||||||
|
|
||||||
for (i++; i < arg_count ; i++)
|
for (i++; i < arg_count ; i++)
|
||||||
{
|
{
|
||||||
if (!(res2= args[i]->val_str(use_as_buff)) || !res2->length())
|
if (!(res2= args[i]->val_str(use_as_buff)))
|
||||||
continue; // Skip NULL and empty string
|
continue; // Skip NULL
|
||||||
|
|
||||||
if (res->length() + sep_str->length() + res2->length() >
|
if (res->length() + sep_str->length() + res2->length() >
|
||||||
current_thd->variables.max_allowed_packet)
|
current_thd->variables.max_allowed_packet)
|
||||||
|
|
|
@ -1573,9 +1573,27 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char llbuff[22];
|
char llbuff[22];
|
||||||
enum enum_duplicates handle_dup = DUP_IGNORE;
|
enum enum_duplicates handle_dup;
|
||||||
if (sql_ex.opt_flags & REPLACE_FLAG)
|
if (sql_ex.opt_flags & REPLACE_FLAG)
|
||||||
handle_dup= DUP_REPLACE;
|
handle_dup= DUP_REPLACE;
|
||||||
|
else if (sql_ex.opt_flags & IGNORE_FLAG)
|
||||||
|
handle_dup= DUP_IGNORE;
|
||||||
|
else
|
||||||
|
/*
|
||||||
|
Note that when replication is running fine, if it was DUP_ERROR on the
|
||||||
|
master then we could choose DUP_IGNORE here, because if DUP_ERROR
|
||||||
|
suceeded on master, and data is identical on the master and slave,
|
||||||
|
then there should be no uniqueness errors on slave, so DUP_IGNORE is
|
||||||
|
the same as DUP_ERROR. But in the unlikely case of uniqueness errors
|
||||||
|
(because the data on the master and slave happen to be different (user
|
||||||
|
error or bug), we want LOAD DATA to print an error message on the
|
||||||
|
slave to discover the problem.
|
||||||
|
|
||||||
|
If reading from net (a 3.23 master), mysql_load() will change this
|
||||||
|
to DUP_IGNORE.
|
||||||
|
*/
|
||||||
|
handle_dup= DUP_ERROR;
|
||||||
|
|
||||||
sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG);
|
sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG);
|
||||||
String field_term(sql_ex.field_term,sql_ex.field_term_len,log_cs);
|
String field_term(sql_ex.field_term,sql_ex.field_term_len,log_cs);
|
||||||
String enclosed(sql_ex.enclosed,sql_ex.enclosed_len,log_cs);
|
String enclosed(sql_ex.enclosed,sql_ex.enclosed_len,log_cs);
|
||||||
|
@ -1637,12 +1655,19 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
if (thd->query_error)
|
if (thd->query_error)
|
||||||
{
|
{
|
||||||
int sql_error= thd->net.last_errno;
|
/* this err/sql_errno code is copy-paste from send_error() */
|
||||||
if (!sql_error)
|
const char *err;
|
||||||
sql_error= ER_UNKNOWN_ERROR;
|
int sql_errno;
|
||||||
slave_print_error(rli,sql_error,
|
if ((err=thd->net.last_error)[0])
|
||||||
"Error '%s' running LOAD DATA INFILE",
|
sql_errno=thd->net.last_errno;
|
||||||
ER_SAFE(sql_error));
|
else
|
||||||
|
{
|
||||||
|
sql_errno=ER_UNKNOWN_ERROR;
|
||||||
|
err=ER(sql_errno);
|
||||||
|
}
|
||||||
|
slave_print_error(rli,sql_errno,
|
||||||
|
"Error '%s' running load data infile",
|
||||||
|
err);
|
||||||
free_root(&thd->mem_root,0);
|
free_root(&thd->mem_root,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,7 +267,7 @@ ulong slave_net_timeout;
|
||||||
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
|
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
|
||||||
ulong query_cache_size=0;
|
ulong query_cache_size=0;
|
||||||
ulong com_stat[(uint) SQLCOM_END], com_other;
|
ulong com_stat[(uint) SQLCOM_END], com_other;
|
||||||
ulong bytes_sent, bytes_received;
|
ulong bytes_sent, bytes_received, net_big_packet_count;
|
||||||
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
|
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
|
||||||
ulong query_id, long_query_count, aborted_threads, aborted_connects;
|
ulong query_id, long_query_count, aborted_threads, aborted_connects;
|
||||||
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
|
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
|
||||||
|
@ -988,13 +988,20 @@ static void set_user(const char *user)
|
||||||
{
|
{
|
||||||
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
||||||
struct passwd *ent;
|
struct passwd *ent;
|
||||||
|
uid_t user_id= geteuid();
|
||||||
|
|
||||||
// don't bother if we aren't superuser
|
// don't bother if we aren't superuser
|
||||||
if (geteuid())
|
if (user_id)
|
||||||
{
|
{
|
||||||
if (user)
|
if (user)
|
||||||
|
{
|
||||||
|
/* Don't give a warning, if real user is same as given with --user */
|
||||||
|
struct passwd *user_info= getpwnam(user);
|
||||||
|
|
||||||
|
if (!user_info || user_id != user_info->pw_uid)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Warning: One can only use the --user switch if running as root\n");
|
"Warning: One can only use the --user switch if running as root\n");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!user)
|
else if (!user)
|
||||||
|
|
|
@ -73,11 +73,13 @@ void sql_print_error(const char *format,...);
|
||||||
#define USE_QUERY_CACHE
|
#define USE_QUERY_CACHE
|
||||||
extern uint test_flags;
|
extern uint test_flags;
|
||||||
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
||||||
extern ulong bytes_sent, bytes_received;
|
extern ulong bytes_sent, bytes_received, net_big_packet_count;
|
||||||
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
||||||
#else
|
#else
|
||||||
#undef statistic_add
|
#undef statistic_add
|
||||||
|
#undef statistic_increment
|
||||||
#define statistic_add(A,B,C)
|
#define statistic_add(A,B,C)
|
||||||
|
#define statistic_increment(A,B)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TEST_BLOCKING 8
|
#define TEST_BLOCKING 8
|
||||||
|
@ -562,7 +564,7 @@ static my_bool net_safe_read(NET *net, char *buff, uint32 length,
|
||||||
if ((tmp=vio_read(net->vio,(char*) net->buff, length)) <= 0)
|
if ((tmp=vio_read(net->vio,(char*) net->buff, length)) <= 0)
|
||||||
{
|
{
|
||||||
my_bool interrupted = vio_should_retry(net->vio);
|
my_bool interrupted = vio_should_retry(net->vio);
|
||||||
if (!thr_got_alarm(&alarmed) && interrupted)
|
if (!thr_got_alarm(alarmed) && interrupted)
|
||||||
{ /* Probably in MIT threads */
|
{ /* Probably in MIT threads */
|
||||||
if (retry_count++ < net->retry_count)
|
if (retry_count++ < net->retry_count)
|
||||||
continue;
|
continue;
|
||||||
|
@ -596,10 +598,13 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
|
||||||
DBUG_ENTER("my_net_skip_rest");
|
DBUG_ENTER("my_net_skip_rest");
|
||||||
DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
|
DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
|
||||||
|
|
||||||
if (!thr_alarm_in_use(&alarmed))
|
/* The following is good for debugging */
|
||||||
|
statistic_increment(net_big_packet_count,&LOCK_bytes_received);
|
||||||
|
|
||||||
|
if (!thr_alarm_in_use(alarmed))
|
||||||
{
|
{
|
||||||
my_bool old_mode;
|
my_bool old_mode;
|
||||||
if (!thr_alarm(alarmed,net->read_timeout, alarm_buff) ||
|
if (thr_alarm(alarmed,net->read_timeout, alarm_buff) ||
|
||||||
vio_blocking(net->vio, TRUE, &old_mode) < 0)
|
vio_blocking(net->vio, TRUE, &old_mode) < 0)
|
||||||
DBUG_RETURN(1); /* Can't setup, abort */
|
DBUG_RETURN(1); /* Can't setup, abort */
|
||||||
}
|
}
|
||||||
|
|
11
sql/slave.cc
11
sql/slave.cc
|
@ -287,7 +287,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
|
||||||
goto err;
|
goto err;
|
||||||
rli->cur_log = &rli->cache_buf;
|
rli->cur_log = &rli->cache_buf;
|
||||||
}
|
}
|
||||||
if (pos > BIN_LOG_HEADER_SIZE)
|
if (pos >= BIN_LOG_HEADER_SIZE)
|
||||||
my_b_seek(rli->cur_log,(off_t)pos);
|
my_b_seek(rli->cur_log,(off_t)pos);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -2154,8 +2154,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sql_print_error("\
|
sql_print_error("\
|
||||||
Could not parse log event entry, check the master for binlog corruption\n\
|
Could not parse relay log event entry. The possible reasons are: the master's \
|
||||||
This may also be a network problem, or just a bug in the master or slave code.\
|
binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
|
||||||
|
binary log), the slave's relay log is corrupted (you can check this by running \
|
||||||
|
'mysqlbinlog' on the relay log), a network problem, or a bug in the master's \
|
||||||
|
or slave's MySQL code. If you want to check the master's binary log or slave's \
|
||||||
|
relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \
|
||||||
|
on this slave.\
|
||||||
");
|
");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -891,6 +891,10 @@ pthread_handler_decl(handle_one_connection,arg)
|
||||||
send_error(thd,net->last_errno,NullS);
|
send_error(thd,net->last_errno,NullS);
|
||||||
statistic_increment(aborted_threads,&LOCK_status);
|
statistic_increment(aborted_threads,&LOCK_status);
|
||||||
}
|
}
|
||||||
|
else if (thd->killed)
|
||||||
|
{
|
||||||
|
statistic_increment(aborted_threads,&LOCK_status);
|
||||||
|
}
|
||||||
|
|
||||||
end_thread:
|
end_thread:
|
||||||
close_connection(thd, 0, 1);
|
close_connection(thd, 0, 1);
|
||||||
|
@ -1068,7 +1072,10 @@ bool do_command(THD *thd)
|
||||||
vio_description(net->vio)));
|
vio_description(net->vio)));
|
||||||
/* Check if we can continue without closing the connection */
|
/* Check if we can continue without closing the connection */
|
||||||
if (net->error != 3)
|
if (net->error != 3)
|
||||||
|
{
|
||||||
|
statistic_increment(aborted_threads,&LOCK_status);
|
||||||
DBUG_RETURN(TRUE); // We have to close it.
|
DBUG_RETURN(TRUE); // We have to close it.
|
||||||
|
}
|
||||||
send_error(thd,net->last_errno,NullS);
|
send_error(thd,net->last_errno,NullS);
|
||||||
net->error= 0;
|
net->error= 0;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
|
@ -997,7 +997,7 @@ int show_binlog_events(THD* thd)
|
||||||
{
|
{
|
||||||
LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
|
LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
|
||||||
ha_rows event_count, limit_start, limit_end;
|
ha_rows event_count, limit_start, limit_end;
|
||||||
my_off_t pos = lex_mi->pos;
|
my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly
|
||||||
char search_file_name[FN_REFLEN], *name;
|
char search_file_name[FN_REFLEN], *name;
|
||||||
const char *log_file_name = lex_mi->log_file_name;
|
const char *log_file_name = lex_mi->log_file_name;
|
||||||
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
|
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
|
||||||
|
@ -1025,12 +1025,6 @@ int show_binlog_events(THD* thd)
|
||||||
if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0)
|
if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (pos < 4)
|
|
||||||
{
|
|
||||||
errmsg = "Invalid log position";
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(log_lock);
|
pthread_mutex_lock(log_lock);
|
||||||
my_b_seek(&log, pos);
|
my_b_seek(&log, pos);
|
||||||
|
|
||||||
|
|
|
@ -804,6 +804,18 @@ master_def:
|
||||||
MASTER_LOG_POS_SYM EQ ulonglong_num
|
MASTER_LOG_POS_SYM EQ ulonglong_num
|
||||||
{
|
{
|
||||||
Lex->mi.pos = $3;
|
Lex->mi.pos = $3;
|
||||||
|
/*
|
||||||
|
If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
|
||||||
|
instead of causing subsequent errors.
|
||||||
|
We need to do it in this file, because only there we know that
|
||||||
|
MASTER_LOG_POS has been explicitely specified. On the contrary
|
||||||
|
in change_master() (sql_repl.cc) we cannot distinguish between 0
|
||||||
|
(MASTER_LOG_POS explicitely specified as 0) and 0 (unspecified),
|
||||||
|
whereas we want to distinguish (specified 0 means "read the binlog
|
||||||
|
from 0" (4 in fact), unspecified means "don't change the position
|
||||||
|
(keep the preceding value)").
|
||||||
|
*/
|
||||||
|
Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos);
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
MASTER_CONNECT_RETRY_SYM EQ ULONG_NUM
|
MASTER_CONNECT_RETRY_SYM EQ ULONG_NUM
|
||||||
|
@ -819,6 +831,8 @@ master_def:
|
||||||
RELAY_LOG_POS_SYM EQ ULONG_NUM
|
RELAY_LOG_POS_SYM EQ ULONG_NUM
|
||||||
{
|
{
|
||||||
Lex->mi.relay_log_pos = $3;
|
Lex->mi.relay_log_pos = $3;
|
||||||
|
/* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
|
||||||
|
Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -141,10 +141,13 @@
|
||||||
*/
|
*/
|
||||||
#define MIN_TURBOBM_PATTERN_LEN 3
|
#define MIN_TURBOBM_PATTERN_LEN 3
|
||||||
|
|
||||||
/* Defines for binary logging */
|
/*
|
||||||
|
Defines for binary logging.
|
||||||
|
Do not decrease the value of BIN_LOG_HEADER_SIZE.
|
||||||
|
Do not even increase it before checking code.
|
||||||
|
*/
|
||||||
|
|
||||||
#define BIN_LOG_HEADER_SIZE 4
|
#define BIN_LOG_HEADER_SIZE 4
|
||||||
|
|
||||||
#define FLOATING_POINT_BUFFER 331
|
#define FLOATING_POINT_BUFFER 331
|
||||||
|
|
||||||
/* Include prototypes for unireg */
|
/* Include prototypes for unireg */
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
# Required-Start: $local_fs $network $remote_fs
|
# Required-Start: $local_fs $network $remote_fs
|
||||||
# Required-Stop: $local_fs $network $remote_fs
|
# Required-Stop: $local_fs $network $remote_fs
|
||||||
# Default-Start: 2 3 4 5
|
# Default-Start: 2 3 4 5
|
||||||
# Default-Stop: 2 3 4 5
|
# Default-Stop: 0 1 6
|
||||||
# Short-Description: start and stop MySQL
|
# Short-Description: start and stop MySQL
|
||||||
# Description: MySQL is a very fast and reliable SQL database engine.
|
# Description: MySQL is a very fast and reliable SQL database engine.
|
||||||
### END INIT INFO
|
### END INIT INFO
|
||||||
|
|
|
@ -254,6 +254,13 @@ export PATH
|
||||||
# Build the 4.0 Max binary (includes BDB and UDFs and therefore
|
# Build the 4.0 Max binary (includes BDB and UDFs and therefore
|
||||||
# cannot be linked statically against the patched glibc)
|
# cannot be linked statically against the patched glibc)
|
||||||
|
|
||||||
|
# If we want to compile with RAID using gcc 3, we need to use
|
||||||
|
# gcc instead of g++ to avoid linking problems (RAID code is written in C++)
|
||||||
|
if gcc -v 2>&1 | grep 'version 3' > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
export CXX="gcc"
|
||||||
|
fi
|
||||||
|
|
||||||
BuildMySQL "--enable-shared \
|
BuildMySQL "--enable-shared \
|
||||||
--with-openssl \
|
--with-openssl \
|
||||||
--with-berkeley-db \
|
--with-berkeley-db \
|
||||||
|
@ -319,6 +326,10 @@ install -m644 $MBD/sql/mysqld.sym $RBR/usr/lib/mysql/mysqld.sym
|
||||||
install -m644 $MBD/support-files/mysql-log-rotate $RBR/etc/logrotate.d/mysql
|
install -m644 $MBD/support-files/mysql-log-rotate $RBR/etc/logrotate.d/mysql
|
||||||
install -m755 $MBD/support-files/mysql.server $RBR/etc/init.d/mysql
|
install -m755 $MBD/support-files/mysql.server $RBR/etc/init.d/mysql
|
||||||
|
|
||||||
|
# Create a symlink "rcmysql", pointing to the init.script. SuSE users
|
||||||
|
# will appreciate that, as all services usually offer this.
|
||||||
|
ln -s ../../sbin/init.d/mysql $RPM_BUILD_ROOT/usr/sbin/rcmysql
|
||||||
|
|
||||||
# Create symbolic compatibility link safe_mysqld -> mysqld_safe
|
# Create symbolic compatibility link safe_mysqld -> mysqld_safe
|
||||||
# (safe_mysqld will be gone in MySQL 4.1)
|
# (safe_mysqld will be gone in MySQL 4.1)
|
||||||
ln -sf ./mysqld_safe $RBR/usr/bin/safe_mysqld
|
ln -sf ./mysqld_safe $RBR/usr/bin/safe_mysqld
|
||||||
|
@ -463,6 +474,7 @@ fi
|
||||||
%attr(755, root, root) /usr/bin/safe_mysqld
|
%attr(755, root, root) /usr/bin/safe_mysqld
|
||||||
|
|
||||||
%attr(755, root, root) /usr/sbin/mysqld
|
%attr(755, root, root) /usr/sbin/mysqld
|
||||||
|
%attr(755, root, root) /usr/sbin/rcmysql
|
||||||
%attr(644, root, root) /usr/lib/mysql/mysqld.sym
|
%attr(644, root, root) /usr/lib/mysql/mysqld.sym
|
||||||
|
|
||||||
%attr(644, root, root) /etc/logrotate.d/mysql
|
%attr(644, root, root) /etc/logrotate.d/mysql
|
||||||
|
|
Loading…
Add table
Reference in a new issue