13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
#include <plugin/multi_thread/multi_thread.h>
18
#include "drizzled/pthread_globals.h"
19
#include <boost/program_options.hpp>
20
#include <drizzled/module/option_map.h>
21
#include <drizzled/errmsg_print.h>
22
#include "drizzled/session.h"
23
#include "drizzled/session/cache.h"
25
#include <boost/thread.hpp>
26
#include <boost/bind.hpp>
28
namespace po= boost::program_options;
16
#include <drizzled/server_includes.h>
17
#include <drizzled/gettext.h>
18
#include <drizzled/error.h>
19
#include <drizzled/plugin_scheduling.h>
20
#include <drizzled/connect.h>
21
#include <drizzled/sql_parse.h>
22
#include <drizzled/session.h>
23
#include <drizzled/connect.h>
29
25
using namespace std;
30
using namespace drizzled;
32
/* Configuration variables. */
33
typedef constrained_check<uint32_t, 4096, 1> max_threads_constraint;
34
static max_threads_constraint max_threads;
38
extern size_t my_thread_stack_size;
41
namespace multi_thread {
43
void MultiThreadScheduler::runSession(drizzled::session_id_t id)
46
boost::this_thread::disable_interruption disable_by_default;
47
Session::shared_ptr session(session::Cache::singleton().find(id));
51
std::cerr << "Session killed before thread could execute\n";
54
session->pushInterrupt(&disable_by_default);
56
if (drizzled::internal::my_thread_init())
58
session->disconnect(drizzled::ER_OUT_OF_RESOURCES, true);
59
session->status_var.aborted_connects++;
60
killSessionNow(session);
62
boost::this_thread::at_thread_exit(&internal::my_thread_end);
64
session->thread_stack= (char*) &stack_dummy;
66
killSessionNow(session);
67
// @todo remove hard spin by disconnection the session first from the
69
while (not session.unique()) {}
72
void MultiThreadScheduler::setStackSize()
76
(void) pthread_attr_init(&attr);
78
/* Get the thread stack size that the OS will use and make sure
79
that we update our global variable. */
80
int err= pthread_attr_getstacksize(&attr, &my_thread_stack_size);
81
pthread_attr_destroy(&attr);
85
errmsg_printf(ERRMSG_LVL_ERROR, _("Unable to get thread stack size\n"));
86
my_thread_stack_size= 524288; // At the time of the writing of this code, this was OSX's
89
if (my_thread_stack_size == 0)
91
my_thread_stack_size= 524288; // At the time of the writing of this code, this was OSX's
95
* Solaris will return zero for the stack size in a call to
96
* pthread_attr_getstacksize() to indicate that the OS default stack
97
* size is used. We need an actual value in my_thread_stack_size so that
98
* check_stack_overrun() will work. The Solaris man page for the
99
* pthread_attr_getstacksize() function says that 2M is used for 64-bit
100
* processes. We'll explicitly set it here to make sure that is what
103
if (my_thread_stack_size == 0)
105
my_thread_stack_size= 2 * 1024 * 1024;
110
bool MultiThreadScheduler::addSession(Session::shared_ptr &session)
112
if (thread_count >= max_threads)
115
thread_count.increment();
117
session->getThread().reset(new boost::thread((boost::bind(&MultiThreadScheduler::runSession, this, session->getSessionId()))));
119
if (not session->getThread())
121
thread_count.decrement();
125
if (not session->getThread()->joinable())
127
thread_count.decrement();
27
pthread_attr_t multi_thread_attrib;
28
static uint32_t max_threads;
30
static bool add_connection(Session *session)
34
safe_mutex_assert_owner(&LOCK_thread_count);
35
(void) pthread_mutex_unlock(&LOCK_thread_count);
37
if ((error= pthread_create(&session->real_id, &multi_thread_attrib, handle_one_connection, (void*) session)))
135
void MultiThreadScheduler::killSession(Session *session)
137
boost_thread_shared_ptr thread(session->getThread());
145
void MultiThreadScheduler::killSessionNow(Session::shared_ptr &session)
147
killSession(session.get());
148
/* Locks LOCK_thread_count and deletes session */
149
Session::unlink(session);
150
thread_count.decrement();
153
MultiThreadScheduler::~MultiThreadScheduler()
155
boost::mutex::scoped_lock scopedLock(drizzled::session::Cache::singleton().mutex());
158
COND_thread_count.wait(scopedLock);
162
} // multi_thread namespace
165
static int init(drizzled::module::Context &context)
168
context.add(new multi_thread::MultiThreadScheduler("multi_thread"));
173
static void init_options(drizzled::module::option_context &context)
175
context("max-threads",
176
po::value<max_threads_constraint>(&max_threads)->default_value(2048),
177
N_("Maximum number of user threads available."));
180
DRIZZLE_DECLARE_PLUGIN
45
End connection, in case when we are using 'no-threads'
48
static bool end_thread(Session *session, bool)
50
unlink_session(session); /* locks LOCK_thread_count and deletes session */
51
pthread_mutex_unlock(&LOCK_thread_count);
54
return true; // We should never reach this point
57
static int init(void *p)
59
scheduling_st* func= (scheduling_st *)p;
61
func->max_threads= max_threads; /* This will create an upper limit on max connections */
62
func->add_connection= add_connection;
63
func->end_thread= end_thread;
65
/* Parameter for threads created for connections */
66
(void) pthread_attr_init(&multi_thread_attrib);
67
(void) pthread_attr_setdetachstate(&multi_thread_attrib,
68
PTHREAD_CREATE_DETACHED);
69
pthread_attr_setscope(&multi_thread_attrib, PTHREAD_SCOPE_SYSTEM);
74
static int deinit(void *)
76
pthread_attr_destroy(&multi_thread_attrib);
81
static DRIZZLE_SYSVAR_UINT(max_threads, max_threads,
83
N_("Maximum number of user threads available."),
84
NULL, NULL, 2048, 1, 4048, 0);
86
static struct st_mysql_sys_var* system_variables[]= {
87
DRIZZLE_SYSVAR(max_threads),
91
drizzle_declare_plugin(multi_thread)
93
DRIZZLE_SCHEDULING_PLUGIN,
186
"One Thread Per Session Scheduler",
97
"One Thread Perl Session Scheduler",
187
98
PLUGIN_LICENSE_GPL,
188
99
init, /* Plugin Init */
189
NULL, /* system variables */
190
init_options /* config options */
100
deinit, /* Plugin Deinit */
101
NULL, /* status variables */
102
system_variables, /* system variables */
103
NULL /* config options */
192
DRIZZLE_DECLARE_PLUGIN_END;
105
drizzle_declare_plugin_end;