~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/multi_thread/multi_thread.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 09:12:23 UTC
  • mto: (511.1.6 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016091223-17ngih0qu9vssjs3
We pass -Wunused-macros now!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2006 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
#include "config.h"
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
 
 
23
 
#include <boost/thread.hpp>
24
 
#include <boost/bind.hpp>
25
 
 
26
 
namespace po= boost::program_options;
27
 
using namespace std;
28
 
using namespace drizzled;
29
 
 
30
 
/* Configuration variables. */
31
 
static uint32_t max_threads;
32
 
 
33
 
/* Global's (TBR) */
34
 
static MultiThreadScheduler *scheduler= NULL;
35
 
 
36
 
namespace drizzled
37
 
{
38
 
  extern size_t my_thread_stack_size;
39
 
}
40
 
 
41
 
void MultiThreadScheduler::runSession(drizzled::Session *session)
42
 
{
43
 
  if (drizzled::internal::my_thread_init())
44
 
  {
45
 
    session->disconnect(drizzled::ER_OUT_OF_RESOURCES, true);
46
 
    session->status_var.aborted_connects++;
47
 
    killSessionNow(session);
48
 
  }
49
 
  boost::this_thread::at_thread_exit(&internal::my_thread_end);
50
 
 
51
 
  session->thread_stack= (char*) &session;
52
 
  session->run();
53
 
  killSessionNow(session);
54
 
}
55
 
 
56
 
void MultiThreadScheduler::setStackSize()
57
 
{
58
 
  pthread_attr_t attr;
59
 
 
60
 
  (void) pthread_attr_init(&attr);
61
 
 
62
 
  /* Get the thread stack size that the OS will use and make sure
63
 
    that we update our global variable. */
64
 
  int err= pthread_attr_getstacksize(&attr, &my_thread_stack_size);
65
 
  pthread_attr_destroy(&attr);
66
 
 
67
 
  if (err != 0)
68
 
  {
69
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Unable to get thread stack size\n"));
70
 
    my_thread_stack_size= 524288; // At the time of the writing of this code, this was OSX's
71
 
  }
72
 
 
73
 
  if (my_thread_stack_size == 0)
74
 
  {
75
 
    my_thread_stack_size= 524288; // At the time of the writing of this code, this was OSX's
76
 
  }
77
 
#ifdef __sun
78
 
  /*
79
 
   * Solaris will return zero for the stack size in a call to
80
 
   * pthread_attr_getstacksize() to indicate that the OS default stack
81
 
   * size is used. We need an actual value in my_thread_stack_size so that
82
 
   * check_stack_overrun() will work. The Solaris man page for the
83
 
   * pthread_attr_getstacksize() function says that 2M is used for 64-bit
84
 
   * processes. We'll explicitly set it here to make sure that is what
85
 
   * will be used.
86
 
   */
87
 
  if (my_thread_stack_size == 0)
88
 
  {
89
 
    my_thread_stack_size= 2 * 1024 * 1024;
90
 
  }
91
 
#endif
92
 
}
93
 
 
94
 
bool MultiThreadScheduler::addSession(Session *session)
95
 
{
96
 
  if (thread_count >= max_threads)
97
 
    return true;
98
 
 
99
 
  thread_count.increment();
100
 
 
101
 
  boost::thread new_thread(boost::bind(&MultiThreadScheduler::runSession, this, session));
102
 
 
103
 
  if (not new_thread.joinable())
104
 
  {
105
 
    thread_count.decrement();
106
 
    return true;
107
 
  }
108
 
 
109
 
  return false;
110
 
}
111
 
 
112
 
 
113
 
void MultiThreadScheduler::killSessionNow(Session *session)
114
 
{
115
 
  /* Locks LOCK_thread_count and deletes session */
116
 
  Session::unlink(session);
117
 
  thread_count.decrement();
118
 
}
119
 
 
120
 
MultiThreadScheduler::~MultiThreadScheduler()
121
 
{
122
 
  boost::mutex::scoped_lock scopedLock(LOCK_thread_count);
123
 
  while (thread_count)
124
 
  {
125
 
    COND_thread_count.wait(scopedLock);
126
 
  }
127
 
}
128
 
 
129
 
  
130
 
static int init(drizzled::module::Context &context)
131
 
{
132
 
  
133
 
  const module::option_map &vm= context.getOptions();
134
 
  if (vm.count("max-threads"))
135
 
  {
136
 
    if (max_threads > 4096 || max_threads < 1)
137
 
    {
138
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for max-threads\n"));
139
 
      exit(-1);
140
 
    }
141
 
  }
142
 
 
143
 
  scheduler= new MultiThreadScheduler("multi_thread");
144
 
  context.add(scheduler);
145
 
 
146
 
  return 0;
147
 
}
148
 
 
149
 
static DRIZZLE_SYSVAR_UINT(max_threads, max_threads,
150
 
                           PLUGIN_VAR_RQCMDARG,
151
 
                           N_("Maximum number of user threads available."),
152
 
                           NULL, NULL, 2048, 1, 4096, 0);
153
 
 
154
 
static void init_options(drizzled::module::option_context &context)
155
 
{
156
 
  context("max-threads",
157
 
          po::value<uint32_t>(&max_threads)->default_value(2048),
158
 
          N_("Maximum number of user threads available."));
159
 
}
160
 
 
161
 
static drizzle_sys_var* sys_variables[]= {
162
 
  DRIZZLE_SYSVAR(max_threads),
163
 
  NULL
164
 
};
165
 
 
166
 
DRIZZLE_DECLARE_PLUGIN
167
 
{
168
 
  DRIZZLE_VERSION_ID,
169
 
  "multi_thread",
170
 
  "0.1",
171
 
  "Brian Aker",
172
 
  "One Thread Per Session Scheduler",
173
 
  PLUGIN_LICENSE_GPL,
174
 
  init, /* Plugin Init */
175
 
  sys_variables,   /* system variables */
176
 
  init_options    /* config options */
177
 
}
178
 
DRIZZLE_DECLARE_PLUGIN_END;