summaryrefslogtreecommitdiff
path: root/sql/scheduler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/scheduler.cc')
-rw-r--r--sql/scheduler.cc780
1 files changed, 116 insertions, 664 deletions
diff --git a/sql/scheduler.cc b/sql/scheduler.cc
index 5b8f834aecc..4a5a99bf40e 100644
--- a/sql/scheduler.cc
+++ b/sql/scheduler.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007 MySQL AB
+/* Copyright (C) 2007 MySQL AB, 2008-2010 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,34 +21,13 @@
#pragma implementation
#endif
-#include <mysql_priv.h>
-#if MYSQL_VERSION_ID >= 60000
+#include <sql_priv.h>
+#include "unireg.h" // REQUIRED: for other includes
+#include "scheduler.h"
+#include "sql_connect.h" // init_new_connection_handler_thread
+#include "scheduler.h"
+#include "sql_callback.h"
#include "sql_audit.h"
-#endif
-
-/*
- 'Dummy' functions to be used when we don't need any handling for a scheduler
- event
- */
-
-static bool init_dummy(void) {return 0;}
-static void post_kill_dummy(THD *thd) {}
-static void end_dummy(void) {}
-static bool end_thread_dummy(THD *thd, bool cache_thread) { return 0; }
-
-/*
- Initialize default scheduler with dummy functions so that setup functions
- only need to declare those that are relvant for their usage
-*/
-
-scheduler_functions::scheduler_functions()
- :init(init_dummy),
- init_new_connection_thread(init_new_connection_handler_thread),
- add_connection(0), // Must be defined
- post_kill_notification(post_kill_dummy),
- end_thread(end_thread_dummy), end(end_dummy)
-{}
-
/*
End connection, in case when we are using 'no-threads'
@@ -57,700 +36,173 @@ scheduler_functions::scheduler_functions()
static bool no_threads_end(THD *thd, bool put_in_cache)
{
unlink_thd(thd);
- pthread_mutex_unlock(&LOCK_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
return 1; // Abort handle_one_connection
}
-
-/*
- Initailize scheduler for --thread-handling=no-threads
-*/
-
-void one_thread_scheduler(scheduler_functions *func)
+static scheduler_functions one_thread_scheduler_functions=
{
- func->max_threads= 1;
- max_connections= 1;
- func->max_connections= &max_connections;
- func->connection_count= &connection_count;
+ 1, // max_threads
+ NULL, NULL,
+ NULL, // init
+ init_new_connection_handler_thread, // init_new_connection_thread
#ifndef EMBEDDED_LIBRARY
- func->add_connection= handle_connection_in_main_thread;
-#endif
- func->init_new_connection_thread= init_dummy;
- func->end_thread= no_threads_end;
-}
-
-
-/*
- Initialize scheduler for --thread-handling=one-thread-per-connection
-*/
+ handle_connection_in_main_thread, // add_connection
+#else
+ NULL, // add_connection
+#endif // EMBEDDED_LIBRARY
+ NULL, // thd_wait_begin
+ NULL, // thd_wait_end
+ NULL, // post_kill_notification
+ no_threads_end, // end_thread
+ NULL, // end
+};
#ifndef EMBEDDED_LIBRARY
-void one_thread_per_connection_scheduler(scheduler_functions *func,
- ulong *arg_max_connections,
- uint *arg_connection_count)
-{
- func->max_threads= *arg_max_connections + 1;
- func->max_connections= arg_max_connections;
- func->connection_count= arg_connection_count;
- func->add_connection= create_thread_to_handle_connection;
- func->end_thread= one_thread_per_connection_end;
-}
-#endif /* EMBEDDED_LIBRARY */
-
-
-#if defined(HAVE_LIBEVENT) && HAVE_POOL_OF_THREADS == 1
-
-#include "event.h"
-
-static struct event_base *base;
-
-static uint created_threads, killed_threads;
-static bool kill_pool_threads;
-
-static struct event thd_add_event;
-static struct event thd_kill_event;
-
-static pthread_mutex_t LOCK_thd_add; /* protects thds_need_adding */
-static LIST *thds_need_adding; /* list of thds to add to libevent queue */
-
-static int thd_add_pair[2]; /* pipe to signal add a connection to libevent*/
-static int thd_kill_pair[2]; /* pipe to signal kill a connection in libevent */
-
-/*
- LOCK_event_loop protects the non-thread safe libevent calls (event_add and
- event_del) and thds_need_processing and thds_waiting_for_io.
-*/
-static pthread_mutex_t LOCK_event_loop;
-static LIST *thds_need_processing; /* list of thds that needs some processing */
-static LIST *thds_waiting_for_io; /* list of thds with added events */
-
-pthread_handler_t libevent_thread_proc(void *arg);
-static void libevent_end();
-static bool libevent_needs_immediate_processing(THD *thd);
-static void libevent_connection_close(THD *thd);
-static bool libevent_should_close_connection(THD* thd);
-static void libevent_thd_add(THD* thd);
-void libevent_io_callback(int Fd, short Operation, void *ctx);
-void libevent_add_thd_callback(int Fd, short Operation, void *ctx);
-void libevent_kill_thd_callback(int Fd, short Operation, void *ctx);
-
-
-/*
- Create a pipe and set to non-blocking.
- Returns TRUE if there is an error.
-*/
-
-static bool init_socketpair(int sock_pair[])
-{
- sock_pair[0]= sock_pair[1]= -1;
- return (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair) < 0 ||
- evutil_make_socket_nonblocking(sock_pair[0]) == -1 ||
- evutil_make_socket_nonblocking(sock_pair[1]) == -1);
-}
-
-static void close_socketpair(int sock_pair[])
+static scheduler_functions one_thread_per_connection_scheduler_functions=
{
- if (sock_pair[0] != -1)
- EVUTIL_CLOSESOCKET(sock_pair[0]);
- if (sock_pair[1] != -1)
- EVUTIL_CLOSESOCKET(sock_pair[1]);
-}
+ 0, // max_threads
+ NULL, NULL,
+ NULL, // init
+ init_new_connection_handler_thread, // init_new_connection_thread
+ create_thread_to_handle_connection, // add_connection
+ NULL, // thd_wait_begin
+ NULL, // thd_wait_end
+ NULL, // post_kill_notification
+ one_thread_per_connection_end, // end_thread
+ NULL, // end
+};
+#endif // EMBEDDED_LIBRARY
-/*
- thd_scheduler keeps the link between THD and events.
- It's embedded in the THD class.
+/** @internal
+ Helper functions to allow mysys to call the thread scheduler when
+ waiting for locks.
*/
-thd_scheduler::thd_scheduler()
- : logged_in(FALSE), io_event(NULL), thread_attached(FALSE)
-{
-#ifndef DBUG_OFF
- dbug_explain[0]= '\0';
- set_explain= FALSE;
-#endif
+/**@{*/
+static void scheduler_wait_begin(void) {
+ THD *thd=current_thd;
+ scheduler_functions *func= thd->scheduler;
+ MYSQL_CALLBACK(func,
+ thd_wait_begin, (thd, THD_WAIT_ROW_TABLE_LOCK));
}
-
-thd_scheduler::~thd_scheduler()
-{
- my_free(io_event, MYF(MY_ALLOW_ZERO_PTR));
-}
-
-
-bool thd_scheduler::init(THD *parent_thd)
-{
- io_event=
- (struct event*)my_malloc(sizeof(*io_event),MYF(MY_ZEROFILL|MY_WME));
-
- if (!io_event)
- {
- sql_print_error("Memory allocation error in thd_scheduler::init\n");
- return TRUE;
- }
-
- event_set(io_event, (int)parent_thd->net.vio->sd, EV_READ,
- libevent_io_callback, (void*)parent_thd);
-
- list.data= parent_thd;
-
- return FALSE;
-}
-
-
-/*
- Attach/associate the connection with the OS thread, for command processing.
-*/
-
-bool thd_scheduler::thread_attach()
-{
- DBUG_ASSERT(!thread_attached);
- THD* thd = (THD*)list.data;
- if (libevent_should_close_connection(thd) ||
- setup_connection_thread_globals(thd))
- {
- return TRUE;
- }
- my_errno= 0;
- thd->mysys_var->abort= 0;
- thread_attached= TRUE;
-#ifndef DBUG_OFF
- /*
- When we attach the thread for a connection for the first time,
- we know that there is no session value set yet. Thus
- the initial setting of set_explain to FALSE is OK.
- */
- if (set_explain)
- DBUG_SET(dbug_explain);
-#endif
- return FALSE;
-}
-
-
-/*
- Detach/disassociate the connection with the OS thread.
-*/
-
-void thd_scheduler::thread_detach()
-{
- if (thread_attached)
- {
- THD* thd = (THD*)list.data;
- thd->reset_globals();
- thread_attached= FALSE;
-#ifndef DBUG_OFF
- /*
- If during the session @@session.dbug was assigned, the
- dbug options/state has been pushed. Check if this is the
- case, to be able to restore the state when we attach this
- logical connection to a physical thread.
- */
- if (_db_is_pushed_())
- {
- set_explain= TRUE;
- if (DBUG_EXPLAIN(dbug_explain, sizeof(dbug_explain)))
- sql_print_error("thd_scheduler: DBUG_EXPLAIN buffer is too small");
- }
- /* DBUG_POP() is a no-op in case there is no session state */
- DBUG_POP();
-#endif
- }
+static void scheduler_wait_end(void) {
+ THD *thd=current_thd;
+ scheduler_functions *func= thd->scheduler;
+ MYSQL_CALLBACK(func, thd_wait_end, (thd));
}
+/**@}*/
/**
- Create all threads for the thread pool
+ Common scheduler init function.
- NOTES
- After threads are created we wait until all threads has signaled that
- they have started before we return
-
- RETURN
- 0 ok
- 1 We got an error creating the thread pool
- In this case we will abort all created threads
-*/
-
-static bool libevent_init(void)
-{
- uint i;
- DBUG_ENTER("libevent_init");
-
- base= (struct event_base *) event_init();
-
- created_threads= 0;
- killed_threads= 0;
- kill_pool_threads= FALSE;
-
- pthread_mutex_init(&LOCK_event_loop, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&LOCK_thd_add, MY_MUTEX_INIT_FAST);
-
- /* set up sockets used to add new thds to the event pool */
- if (init_socketpair(thd_add_pair))
- {
- sql_print_error("init_socketpair(thd_add_spair) error in libevent_init");
- DBUG_RETURN(1);
- }
- /* set up sockets used to kill thds in the event queue */
- if (init_socketpair(thd_kill_pair))
- {
- sql_print_error("init_socketpair(thd_kill_pair) error in libevent_init");
- close_socketpair(thd_add_pair);
- DBUG_RETURN(1);
- }
- event_set(&thd_add_event, thd_add_pair[0], EV_READ|EV_PERSIST,
- libevent_add_thd_callback, NULL);
- event_set(&thd_kill_event, thd_kill_pair[0], EV_READ|EV_PERSIST,
- libevent_kill_thd_callback, NULL);
-
- if (event_add(&thd_add_event, NULL) || event_add(&thd_kill_event, NULL))
- {
- sql_print_error("thd_add_event event_add error in libevent_init");
- libevent_end();
- DBUG_RETURN(1);
- }
- /* Set up the thread pool */
- created_threads= killed_threads= 0;
- pthread_mutex_lock(&LOCK_thread_count);
-
- for (i= 0; i < thread_pool_size; i++)
- {
- pthread_t thread;
- int error;
- if ((error= pthread_create(&thread, &connection_attrib,
- libevent_thread_proc, 0)))
- {
- sql_print_error("Can't create completion port thread (error %d)",
- error);
- pthread_mutex_unlock(&LOCK_thread_count);
- libevent_end(); // Cleanup
- DBUG_RETURN(TRUE);
- }
- }
-
- /* Wait until all threads are created */
- while (created_threads != thread_pool_size)
- pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- pthread_mutex_unlock(&LOCK_thread_count);
-
- DBUG_PRINT("info", ("%u threads created", (uint) thread_pool_size));
- DBUG_RETURN(FALSE);
+ The scheduler is either initialized by calling
+ one_thread_scheduler() or one_thread_per_connection_scheduler() in
+ mysqld.cc, so this init function will always be called.
+ */
+static void scheduler_init() {
+ mysys_var->scheduler_before_lock_wait= &scheduler_wait_begin;
+ mysys_var->scheduler_after_lock_wait= &scheduler_wait_end;
}
-
/*
- This is called when data is ready on the socket.
-
- NOTES
- This is only called by the thread that owns LOCK_event_loop.
-
- We add the thd that got the data to thds_need_processing, and
- cause the libevent event_loop() to terminate. Then this same thread will
- return from event_loop and pick the thd value back up for processing.
+ Initialize scheduler for --thread-handling=one-thread-per-connection
*/
-void libevent_io_callback(int, short, void *ctx)
+#ifndef EMBEDDED_LIBRARY
+scheduler_functions *one_thread_per_connection_scheduler(
+ ulong *arg_max_connections,
+ uint *arg_connection_count)
{
- safe_mutex_assert_owner(&LOCK_event_loop);
- THD *thd= (THD*)ctx;
- thds_waiting_for_io= list_delete(thds_waiting_for_io, &thd->event_scheduler.list);
- thds_need_processing= list_add(thds_need_processing, &thd->event_scheduler.list);
+ scheduler_init();
+ one_thread_per_connection_scheduler_functions.max_threads= *arg_max_connections + 1;
+ one_thread_per_connection_scheduler_functions.max_connections= arg_max_connections;
+ one_thread_per_connection_scheduler_functions.connection_count= arg_connection_count;
+ return &one_thread_per_connection_scheduler_functions;
}
+#endif
/*
- This is called when we have a thread we want to be killed.
-
- NOTES
- This is only called by the thread that owns LOCK_event_loop.
+ Initailize scheduler for --thread-handling=no-threads
*/
-void libevent_kill_thd_callback(int Fd, short, void*)
+scheduler_functions *one_thread_scheduler()
{
- safe_mutex_assert_owner(&LOCK_event_loop);
-
- /* clear the pending events */
- char c;
- while (recv(Fd, &c, sizeof(c), 0) == sizeof(c))
- {}
-
- LIST* list= thds_waiting_for_io;
- while (list)
- {
- THD *thd= (THD*)list->data;
- list= list_rest(list);
- if (thd->killed == THD::KILL_CONNECTION)
- {
- /*
- Delete from libevent and add to the processing queue.
- */
- event_del(thd->event_scheduler.io_event);
- thds_waiting_for_io= list_delete(thds_waiting_for_io,
- &thd->event_scheduler.list);
- thds_need_processing= list_add(thds_need_processing,
- &thd->event_scheduler.list);
- }
- }
+ scheduler_init();
+ return &one_thread_scheduler_functions;
}
/*
- This is used to add connections to the pool. This callback is invoked from
- the libevent event_loop() call whenever the thd_add_pair[1] has a byte
- written to it.
-
- NOTES
- This is only called by the thread that owns LOCK_event_loop.
-*/
-
-void libevent_add_thd_callback(int Fd, short, void *)
-{
- safe_mutex_assert_owner(&LOCK_event_loop);
-
- /* clear the pending events */
- char c;
- while (recv(Fd, &c, sizeof(c), 0) == sizeof(c))
- {}
-
- pthread_mutex_lock(&LOCK_thd_add);
- while (thds_need_adding)
- {
- /* pop the first thd off the list */
- THD* thd= (THD*)thds_need_adding->data;
- thds_need_adding= list_delete(thds_need_adding, thds_need_adding);
-
- pthread_mutex_unlock(&LOCK_thd_add);
-
- if (!thd->event_scheduler.logged_in || libevent_should_close_connection(thd))
- {
- /*
- Add thd to thds_need_processing list. If it needs closing we'll close
- it outside of event_loop().
- */
- thds_need_processing= list_add(thds_need_processing,
- &thd->event_scheduler.list);
- }
- else
- {
- /* Add to libevent */
- if (event_add(thd->event_scheduler.io_event, NULL))
- {
- sql_print_error("event_add error in libevent_add_thd_callback");
- libevent_connection_close(thd);
- }
- else
- {
- thds_waiting_for_io= list_add(thds_waiting_for_io,
- &thd->event_scheduler.list);
- }
- }
- pthread_mutex_lock(&LOCK_thd_add);
- }
- pthread_mutex_unlock(&LOCK_thd_add);
-}
-
-
-/**
- Notify the thread pool about a new connection
-
- NOTES
- LOCK_thread_count is locked on entry. This function MUST unlock it!
-*/
-
-static void libevent_add_connection(THD *thd)
-{
- DBUG_ENTER("libevent_add_connection");
- DBUG_PRINT("enter", ("thd: %p thread_id: %lu",
- thd, thd->thread_id));
-
- if (thd->event_scheduler.init(thd))
- {
- sql_print_error("Scheduler init error in libevent_add_new_connection");
- pthread_mutex_unlock(&LOCK_thread_count);
- libevent_connection_close(thd);
- DBUG_VOID_RETURN;
- }
- threads.append(thd);
- libevent_thd_add(thd);
-
- pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_VOID_RETURN;
-}
-
-
-/**
- @brief Signal a waiting connection it's time to die.
-
- @details This function will signal libevent the THD should be killed.
- Either the global LOCK_thd_count or the THD's LOCK_thd_data must be locked
- upon entry.
-
- @param[in] thd The connection to kill
+ Initialize scheduler for --thread-handling=one-thread-per-connection
*/
-static void libevent_post_kill_notification(THD *)
-{
- /*
- Note, we just wake up libevent with an event that a THD should be killed,
- It will search its list of thds for thd->killed == KILL_CONNECTION to
- find the THDs it should kill.
-
- So we don't actually tell it which one and we don't actually use the
- THD being passed to us, but that's just a design detail that could change
- later.
- */
- char c= 0;
- send(thd_kill_pair[1], &c, sizeof(c), 0);
-}
-
-
/*
- Close and delete a connection.
+ thd_scheduler keeps the link between THD and events.
+ It's embedded in the THD class.
*/
-static void libevent_connection_close(THD *thd)
+thd_scheduler::thd_scheduler()
+ : m_psi(NULL), data(NULL)
{
- DBUG_ENTER("libevent_connection_close");
- DBUG_PRINT("enter", ("thd: %p", thd));
-
- thd->killed= THD::KILL_CONNECTION; // Avoid error messages
-
- if (thd->net.vio->sd >= 0) // not already closed
- {
- end_connection(thd);
- close_connection(thd, 0, 1);
- }
- thd->event_scheduler.thread_detach();
- unlink_thd(thd); /* locks LOCK_thread_count and deletes thd */
- pthread_mutex_unlock(&LOCK_thread_count);
-
- DBUG_VOID_RETURN;
+#ifndef DBUG_OFF
+ dbug_explain[0]= '\0';
+ set_explain= FALSE;
+#endif
}
-/*
- Returns true if we should close and delete a THD connection.
-*/
-
-static bool libevent_should_close_connection(THD* thd)
+thd_scheduler::~thd_scheduler()
{
- return thd->net.error ||
- thd->net.vio == 0 ||
- thd->killed == THD::KILL_CONNECTION;
}
-
/*
- libevent_thread_proc is the outer loop of each thread in the thread pool.
- These procs only return/terminate on shutdown (kill_pool_threads == true).
+ no pluggable schedulers in mariadb.
+ when we'll want it, we'll do it properly
*/
+#if 0
-pthread_handler_t libevent_thread_proc(void *arg)
-{
- if (init_new_connection_handler_thread())
- {
- my_thread_global_end();
- sql_print_error("libevent_thread_proc: my_thread_init() failed");
- exit(1);
- }
- DBUG_ENTER("libevent_thread_proc");
-
- /*
- Signal libevent_init() when all threads has been created and are ready to
- receive events.
- */
- (void) pthread_mutex_lock(&LOCK_thread_count);
- created_threads++;
- thread_created++;
- if (created_threads == thread_pool_size)
- (void) pthread_cond_signal(&COND_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
-
- for (;;)
- {
- THD *thd= NULL;
- (void) pthread_mutex_lock(&LOCK_event_loop);
-
- /* get thd(s) to process */
- while (!thds_need_processing)
- {
- if (kill_pool_threads)
- {
- /* the flag that we should die has been set */
- (void) pthread_mutex_unlock(&LOCK_event_loop);
- goto thread_exit;
- }
- event_loop(EVLOOP_ONCE);
- }
-
- /* pop the first thd off the list */
- thd= (THD*)thds_need_processing->data;
- thds_need_processing= list_delete(thds_need_processing,
- thds_need_processing);
-
- (void) pthread_mutex_unlock(&LOCK_event_loop);
-
- /* now we process the connection (thd) */
-
- /* set up the thd<->thread links. */
- thd->thread_stack= (char*) &thd;
-
- if (thd->event_scheduler.thread_attach())
- {
- libevent_connection_close(thd);
- continue;
- }
-
- /* is the connection logged in yet? */
- if (!thd->event_scheduler.logged_in)
- {
- DBUG_PRINT("info", ("init new connection. sd: %d",
- thd->net.vio->sd));
- lex_start(thd);
- if (login_connection(thd))
- {
- /* Failed to log in */
- libevent_connection_close(thd);
- continue;
- }
- else
- {
- /* login successful */
-#if MYSQL_VERSION_ID >= 60000
- MYSQL_CONNECTION_START(thd->thread_id, thd->security_ctx->priv_user,
- (char *) thd->security_ctx->host_or_ip);
-#endif
- thd->event_scheduler.logged_in= TRUE;
- prepare_new_connection_state(thd);
- if (!libevent_needs_immediate_processing(thd))
- continue; /* New connection is now waiting for data in libevent*/
- }
- }
-
- do
- {
- /* Process a query */
- if (do_command(thd))
- {
- libevent_connection_close(thd);
- break;
- }
- } while (libevent_needs_immediate_processing(thd));
- }
-
-thread_exit:
- DBUG_PRINT("exit", ("ending thread"));
- (void) pthread_mutex_lock(&LOCK_thread_count);
- killed_threads++;
- pthread_cond_broadcast(&COND_thread_count);
- (void) pthread_mutex_unlock(&LOCK_thread_count);
- my_thread_end();
- pthread_exit(0);
- DBUG_RETURN(0); /* purify: deadcode */
-}
-
-
-/*
- Returns TRUE if the connection needs immediate processing and FALSE if
- instead it's queued for libevent processing or closed,
-*/
+static scheduler_functions *saved_thread_scheduler;
+static uint saved_thread_handling;
-static bool libevent_needs_immediate_processing(THD *thd)
+extern "C"
+int my_thread_scheduler_set(scheduler_functions *scheduler)
{
- if (libevent_should_close_connection(thd))
- {
- libevent_connection_close(thd);
- return FALSE;
- }
- /*
- If more data in the socket buffer, return TRUE to process another command.
-
- Note: we cannot add for event processing because the whole request might
- already be buffered and we wouldn't receive an event.
- */
- if (vio_pending(thd->net.vio) > 0)
- return TRUE;
-
- thd->event_scheduler.thread_detach();
- libevent_thd_add(thd);
- return FALSE;
-}
-
+ DBUG_ASSERT(scheduler != 0);
-/*
- Adds a THD to queued for libevent processing.
-
- This call does not actually register the event with libevent.
- Instead, it places the THD onto a queue and signals libevent by writing
- a byte into thd_add_pair, which will cause our libevent_add_thd_callback to
- be invoked which will find the THD on the queue and add it to libevent.
-*/
+ if (scheduler == NULL)
+ return 1;
-static void libevent_thd_add(THD* thd)
-{
- char c= 0;
- /* release any audit resources, this thd is going to sleep */
-#if MYSQL_VERSION_ID >= 60000
- mysql_audit_release(thd);
-#endif
- pthread_mutex_lock(&LOCK_thd_add);
- /* queue for libevent */
- thds_need_adding= list_add(thds_need_adding, &thd->event_scheduler.list);
- /* notify libevent */
- send(thd_add_pair[1], &c, sizeof(c), 0);
- pthread_mutex_unlock(&LOCK_thd_add);
+ saved_thread_scheduler= thread_scheduler;
+ saved_thread_handling= thread_handling;
+ thread_scheduler= scheduler;
+ // Scheduler loaded dynamically
+ thread_handling= SCHEDULER_TYPES_COUNT;
+ return 0;
}
-/**
- Wait until all pool threads have been deleted for clean shutdown
-*/
-
-static void libevent_end()
+extern "C"
+int my_thread_scheduler_reset()
{
- DBUG_ENTER("libevent_end");
- DBUG_PRINT("enter", ("created_threads: %d killed_threads: %u",
- created_threads, killed_threads));
-
- /*
- check if initialized. This may not be the case if get an error at
- startup
- */
- if (!base)
- DBUG_VOID_RETURN;
-
- (void) pthread_mutex_lock(&LOCK_thread_count);
-
-
- kill_pool_threads= TRUE;
- while (killed_threads != created_threads)
- {
- /* wake up the event loop */
- char c= 0;
- send(thd_add_pair[1], &c, sizeof(c), 0);
- pthread_cond_wait(&COND_thread_count, &LOCK_thread_count);
- }
- (void) pthread_mutex_unlock(&LOCK_thread_count);
-
- event_del(&thd_add_event);
- close_socketpair(thd_add_pair);
- event_del(&thd_kill_event);
- close_socketpair(thd_kill_pair);
- event_base_free(base);
- base= 0;
-
- (void) pthread_mutex_destroy(&LOCK_event_loop);
- (void) pthread_mutex_destroy(&LOCK_thd_add);
- DBUG_VOID_RETURN;
-}
+ DBUG_ASSERT(saved_thread_scheduler != NULL);
+ if (saved_thread_scheduler == NULL)
+ return 1;
-void pool_of_threads_scheduler(scheduler_functions* func)
-{
- func->max_threads= thread_pool_size;
- func->max_connections= &max_connections;
- func->connection_count= &connection_count;
- func->init= libevent_init;
- func->end= libevent_end;
- func->post_kill_notification= libevent_post_kill_notification;
- func->add_connection= libevent_add_connection;
+ thread_scheduler= saved_thread_scheduler;
+ thread_handling= saved_thread_handling;
+ saved_thread_scheduler= 0;
+ return 0;
}
+#else
+extern "C" int my_thread_scheduler_set(scheduler_functions *scheduler)
+{ return 1; }
+extern "C" int my_thread_scheduler_reset()
+{ return 1; }
#endif
+
+#warning restore libevent
+