~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_thr_init.cc

  • Committer: Stewart Smith
  • Date: 2009-05-15 06:57:12 UTC
  • mto: (991.1.5 for-brian)
  • mto: This revision was merged to the branch mainline in revision 1022.
  • Revision ID: stewart@flamingspork.com-20090515065712-bmionylacjmexmmm
Make sql_mode=NO_AUTO_VALUE_ON_ZERO default for Drizzle.

Also fix DEFAULT keyword handling for auto-increment so that it defaults to
NULL and not 0 so that the following is valid and generates two auto-inc
values:

create table t1 (a int auto_increment primary key)
insert into t1 (a) values (default);
insert into t1 (a) values (default);

Important to note that 0 is no longer magic. So this gives you duplicate
primary key error:

insert into t1 (a) values(0);
insert into t1 (a) values(0);

as you've inserted the explicit value of 0 twice.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  Functions to handle initializating and allocationg of all mysys & debug
18
18
  thread variables.
19
19
*/
20
20
 
21
 
#include "config.h"
22
 
 
23
 
#include "drizzled/internal/my_sys.h"
24
 
#include "drizzled/internal/thread_var.h"
25
 
#include "drizzled/internal/m_string.h"
26
 
 
27
 
#include <cstdio>
 
21
#include "mysys/mysys_priv.h"
 
22
#include <mysys/my_pthread.h>
 
23
#include <mystrings/m_string.h>
 
24
 
 
25
#include <stdio.h>
28
26
#include <signal.h>
29
27
 
30
28
#if TIME_WITH_SYS_TIME
38
36
# endif
39
37
#endif
40
38
 
41
 
#include <boost/thread/thread.hpp>
42
 
#include <boost/thread/mutex.hpp>
43
 
#include <boost/thread/tss.hpp>
44
 
 
45
 
namespace drizzled
46
 
{
47
 
namespace internal
48
 
{
49
 
 
50
 
boost::thread_specific_ptr<st_my_thread_var> THR_KEY_mysys;
51
 
boost::mutex THR_LOCK_threads;
 
39
uint32_t thd_lib_detected= 0;
 
40
 
 
41
pthread_key_t THR_KEY_mysys;
 
42
pthread_mutex_t THR_LOCK_open;
 
43
pthread_mutex_t THR_LOCK_lock;
 
44
pthread_mutex_t THR_LOCK_threads;
 
45
pthread_cond_t  THR_COND_threads;
 
46
uint32_t            THR_thread_count= 0;
 
47
uint32_t                my_thread_end_wait_time= 5;
 
48
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
49
pthread_mutexattr_t my_fast_mutexattr;
 
50
#endif
 
51
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
52
pthread_mutexattr_t my_errorcheck_mutexattr;
 
53
#endif
 
54
 
 
55
#ifdef TARGET_OS_LINUX
 
56
 
 
57
/*
 
58
  Dummy thread spawned in my_thread_global_init() below to avoid
 
59
  race conditions in NPTL pthread_exit code.
 
60
*/
 
61
 
 
62
extern "C"
 
63
void *
 
64
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
 
65
{
 
66
  /* Do nothing! */
 
67
  pthread_exit(0);
 
68
  return 0;
 
69
}
 
70
 
 
71
#endif /* TARGET_OS_LINUX */
 
72
 
 
73
 
 
74
static uint32_t get_thread_lib(void);
52
75
 
53
76
/*
54
77
  initialize thread environment
63
86
 
64
87
bool my_thread_global_init(void)
65
88
{
 
89
  int pth_ret;
 
90
  thd_lib_detected= get_thread_lib();
 
91
 
 
92
  if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
 
93
  {
 
94
    fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
 
95
    return 1;
 
96
  }
 
97
 
 
98
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
99
  /*
 
100
    Set mutex type to "fast" a.k.a "adaptive"
 
101
 
 
102
    In this case the thread may steal the mutex from some other thread
 
103
    that is waiting for the same mutex.  This will save us some
 
104
    context switches but may cause a thread to 'starve forever' while
 
105
    waiting for the mutex (not likely if the code within the mutex is
 
106
    short).
 
107
  */
 
108
  pthread_mutexattr_init(&my_fast_mutexattr);
 
109
  pthread_mutexattr_settype(&my_fast_mutexattr,
 
110
                            PTHREAD_MUTEX_ADAPTIVE_NP);
 
111
#endif
 
112
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
113
  /*
 
114
    Set mutex type to "errorcheck"
 
115
  */
 
116
  pthread_mutexattr_init(&my_errorcheck_mutexattr);
 
117
  pthread_mutexattr_settype(&my_errorcheck_mutexattr,
 
118
                            PTHREAD_MUTEX_ERRORCHECK);
 
119
#endif
 
120
 
 
121
  pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
 
122
  pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
 
123
  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
 
124
  pthread_cond_init(&THR_COND_threads, NULL);
66
125
  if (my_thread_init())
67
126
  {
68
127
    my_thread_global_end();                     /* Clean up */
74
133
 
75
134
void my_thread_global_end(void)
76
135
{
 
136
  struct timespec abstime;
 
137
  bool all_threads_killed= 1;
 
138
 
 
139
  set_timespec(abstime, my_thread_end_wait_time);
 
140
  pthread_mutex_lock(&THR_LOCK_threads);
 
141
  while (THR_thread_count > 0)
 
142
  {
 
143
    int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
 
144
                                      &abstime);
 
145
    if (error == ETIMEDOUT || error == ETIME)
 
146
    {
 
147
      /*
 
148
        We shouldn't give an error here, because if we don't have
 
149
        pthread_kill(), programs like mysqld can't ensure that all threads
 
150
        are killed when we enter here.
 
151
      */
 
152
      if (THR_thread_count)
 
153
        fprintf(stderr,
 
154
                "Error in my_thread_global_end(): %d threads didn't exit\n",
 
155
                THR_thread_count);
 
156
      all_threads_killed= 0;
 
157
      break;
 
158
    }
 
159
  }
 
160
  pthread_mutex_unlock(&THR_LOCK_threads);
 
161
 
 
162
  pthread_key_delete(THR_KEY_mysys);
 
163
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
164
  pthread_mutexattr_destroy(&my_fast_mutexattr);
 
165
#endif
 
166
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
167
  pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
 
168
#endif
 
169
  pthread_mutex_destroy(&THR_LOCK_open);
 
170
  pthread_mutex_destroy(&THR_LOCK_lock);
 
171
  if (all_threads_killed)
 
172
  {
 
173
    pthread_mutex_destroy(&THR_LOCK_threads);
 
174
    pthread_cond_destroy(&THR_COND_threads);
 
175
  }
77
176
}
78
177
 
79
 
static uint64_t thread_id= 0;
 
178
static my_thread_id thread_id= 0;
80
179
 
81
180
/*
82
181
  Allocate thread specific memory for the thread, used by mysys
91
190
 
92
191
bool my_thread_init(void)
93
192
{
94
 
  // We should mever see my_thread_init()  called twice
95
 
  if (THR_KEY_mysys.get())
96
 
    return 0;
97
 
 
98
 
  st_my_thread_var *tmp= new st_my_thread_var;
99
 
  if (tmp == NULL)
100
 
  {
101
 
    return true;
102
 
  }
103
 
  THR_KEY_mysys.reset(tmp);
104
 
 
105
 
  boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
 
193
  struct st_my_thread_var *tmp;
 
194
  bool error=0;
 
195
 
 
196
#ifdef EXTRA_DEBUG_THREADS
 
197
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
 
198
          (uint32_t) pthread_self());
 
199
#endif
 
200
 
 
201
  if (pthread_getspecific(THR_KEY_mysys))
 
202
  {
 
203
#ifdef EXTRA_DEBUG_THREADS
 
204
    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
 
205
            (long) pthread_self());
 
206
#endif
 
207
    goto end;
 
208
  }
 
209
  if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
 
210
  {
 
211
    error= 1;
 
212
    goto end;
 
213
  }
 
214
  pthread_setspecific(THR_KEY_mysys,tmp);
 
215
  tmp->pthread_self= pthread_self();
 
216
  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
 
217
  pthread_cond_init(&tmp->suspend, NULL);
 
218
  tmp->init= 1;
 
219
 
 
220
  pthread_mutex_lock(&THR_LOCK_threads);
106
221
  tmp->id= ++thread_id;
 
222
  ++THR_thread_count;
 
223
  pthread_mutex_unlock(&THR_LOCK_threads);
107
224
 
108
 
  return false;
 
225
end:
 
226
  return error;
109
227
}
110
228
 
111
229
 
117
235
 
118
236
  NOTE
119
237
    This may be called multiple times for a thread.
120
 
    This happens for example when one calls 'server_init()'
121
 
    server_end() and then ends with a end().
 
238
    This happens for example when one calls 'mysql_server_init()'
 
239
    mysql_server_end() and then ends with a mysql_end().
122
240
*/
123
241
 
124
242
void my_thread_end(void)
125
243
{
 
244
  struct st_my_thread_var *tmp;
 
245
  tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
 
246
 
 
247
#ifdef EXTRA_DEBUG_THREADS
 
248
  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
 
249
          (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
 
250
#endif
 
251
  if (tmp && tmp->init)
 
252
  {
 
253
#if !defined(__bsdi__) && !defined(__OpenBSD__)
 
254
 /* bsdi and openbsd 3.5 dumps core here */
 
255
    pthread_cond_destroy(&tmp->suspend);
 
256
#endif
 
257
    pthread_mutex_destroy(&tmp->mutex);
 
258
    tmp->init= 0;
 
259
 
 
260
    /*
 
261
      Decrement counter for number of running threads. We are using this
 
262
      in my_thread_global_end() to wait until all threads have called
 
263
      my_thread_end and thus freed all memory they have allocated in
 
264
      my_thread_init()
 
265
    */
 
266
    pthread_mutex_lock(&THR_LOCK_threads);
 
267
    assert(THR_thread_count != 0);
 
268
    if (--THR_thread_count == 0)
 
269
      pthread_cond_signal(&THR_COND_threads);
 
270
   pthread_mutex_unlock(&THR_LOCK_threads);
 
271
  }
126
272
}
127
273
 
128
274
struct st_my_thread_var *_my_thread_var(void)
129
275
{
130
 
  return THR_KEY_mysys.get();
131
 
}
132
 
 
133
 
} /* namespace internal */
134
 
} /* namespace drizzled */
 
276
  struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
 
277
  return tmp;
 
278
}
 
279
 
 
280
 
 
281
/****************************************************************************
 
282
  Get name of current thread.
 
283
****************************************************************************/
 
284
 
 
285
my_thread_id my_thread_dbug_id()
 
286
{
 
287
  return my_thread_var->id;
 
288
}
 
289
 
 
290
static uint32_t get_thread_lib(void)
 
291
{
 
292
#ifdef _CS_GNU_LIBPTHREAD_VERSION
 
293
  char buff[64];
 
294
 
 
295
  confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
 
296
 
 
297
  if (!strncasecmp(buff, "NPTL", 4))
 
298
    return THD_LIB_NPTL;
 
299
  if (!strncasecmp(buff, "linuxthreads", 12))
 
300
    return THD_LIB_LT;
 
301
#endif
 
302
  return THD_LIB_OTHER;
 
303
}