00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017
00018 #include <iostream>
00019
00020 #include <drizzled/pthread_globals.h>
00021 #include <drizzled/module/option_map.h>
00022 #include <drizzled/errmsg_print.h>
00023 #include <drizzled/session.h>
00024 #include <drizzled/session/cache.h>
00025 #include <drizzled/abort_exception.h>
00026 #include <drizzled/transaction_services.h>
00027 #include <drizzled/gettext.h>
00028 #include <drizzled/plugin.h>
00029 #include <drizzled/statistics_variables.h>
00030
00031 #include <boost/thread.hpp>
00032 #include <boost/bind.hpp>
00033 #include <boost/program_options.hpp>
00034
00035 #include "multi_thread.h"
00036
00037 namespace po= boost::program_options;
00038 using namespace std;
00039 using namespace drizzled;
00040
00041
00042 typedef constrained_check<uint32_t, 4096, 1> max_threads_constraint;
00043 static max_threads_constraint max_threads;
00044
00045 namespace drizzled
00046 {
00047 extern size_t my_thread_stack_size;
00048 }
00049
00050 namespace multi_thread {
00051
00052 void MultiThreadScheduler::runSession(drizzled::session_id_t id)
00053 {
00054 char stack_dummy;
00055 boost::this_thread::disable_interruption disable_by_default;
00056
00057 Session::shared_ptr session(session::Cache::find(id));
00058
00059 try
00060 {
00061
00062 if (not session)
00063 {
00064 std::cerr << _("Session killed before thread could execute") << endl;
00065 return;
00066 }
00067 session->pushInterrupt(&disable_by_default);
00068 drizzled::internal::my_thread_init();
00069 session->thread_stack= (char*) &stack_dummy;
00070 session->run();
00071
00072 killSessionNow(session);
00073 }
00074 catch (abort_exception& ex)
00075 {
00076 cout << _("Drizzle has receieved an abort event.") << endl;
00077 cout << _("In Function: ") << *::boost::get_error_info<boost::throw_function>(ex) << endl;
00078 cout << _("In File: ") << *::boost::get_error_info<boost::throw_file>(ex) << endl;
00079 cout << _("On Line: ") << *::boost::get_error_info<boost::throw_line>(ex) << endl;
00080
00081 TransactionServices::sendShutdownEvent(*session.get());
00082 }
00083
00084
00085 while (not session.unique()) {}
00086 }
00087
00088 void MultiThreadScheduler::setStackSize()
00089 {
00090 pthread_attr_t attr;
00091
00092 (void) pthread_attr_init(&attr);
00093
00094
00095
00096 int err= pthread_attr_getstacksize(&attr, &my_thread_stack_size);
00097 pthread_attr_destroy(&attr);
00098
00099 if (err != 0)
00100 {
00101 errmsg_printf(error::ERROR, _("Unable to get thread stack size"));
00102 my_thread_stack_size= 524288;
00103 }
00104
00105 if (my_thread_stack_size == 0)
00106 {
00107 my_thread_stack_size= 524288;
00108 }
00109 #ifdef __sun
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 if (my_thread_stack_size == 0)
00120 {
00121 my_thread_stack_size= 2 * 1024 * 1024;
00122 }
00123 #endif
00124 }
00125
00126 bool MultiThreadScheduler::addSession(const Session::shared_ptr& session)
00127 {
00128 if (thread_count >= max_threads)
00129 return true;
00130
00131 thread_count.increment();
00132 try
00133 {
00134 session->getThread().reset(new boost::thread((boost::bind(&MultiThreadScheduler::runSession, this, session->getSessionId()))));
00135 }
00136 catch (std::exception&)
00137 {
00138 thread_count.decrement();
00139 return true;
00140 }
00141
00142 if (not session->getThread())
00143 {
00144 thread_count.decrement();
00145 return true;
00146 }
00147
00148 if (not session->getThread()->joinable())
00149 {
00150 thread_count.decrement();
00151 return true;
00152 }
00153
00154 return false;
00155 }
00156
00157
00158 void MultiThreadScheduler::killSession(Session *session)
00159 {
00160 thread_ptr thread(session->getThread());
00161
00162 if (thread)
00163 {
00164 thread->interrupt();
00165 }
00166 }
00167
00168 void MultiThreadScheduler::killSessionNow(const Session::shared_ptr& session)
00169 {
00170 killSession(session.get());
00171
00172 session->disconnect();
00173
00174
00175 Session::unlink(session);
00176 thread_count.decrement();
00177 }
00178
00179 MultiThreadScheduler::~MultiThreadScheduler()
00180 {
00181 boost::mutex::scoped_lock scopedLock(drizzled::session::Cache::mutex());
00182 while (thread_count)
00183 {
00184 COND_thread_count.wait(scopedLock);
00185 }
00186 }
00187
00188 }
00189
00190
00191 static int init(drizzled::module::Context &context)
00192 {
00193
00194 context.add(new multi_thread::MultiThreadScheduler("multi_thread"));
00195
00196 return 0;
00197 }
00198
00199 static void init_options(drizzled::module::option_context &context)
00200 {
00201 context("max-threads",
00202 po::value<max_threads_constraint>(&max_threads)->default_value(2048),
00203 _("Maximum number of user threads available."));
00204 }
00205
00206 DRIZZLE_DECLARE_PLUGIN
00207 {
00208 DRIZZLE_VERSION_ID,
00209 "multi_thread",
00210 "0.1",
00211 "Brian Aker",
00212 "One Thread Per Session Scheduler",
00213 PLUGIN_LICENSE_GPL,
00214 init,
00215 NULL,
00216 init_options
00217 }
00218 DRIZZLE_DECLARE_PLUGIN_END;