~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_locking.c

  • Committer: Monty Taylor
  • Date: 2008-08-02 00:06:32 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080802000632-jsse0zdd9r6ic5ku
Actually turn gettext on...

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
  isamdatabase.
21
21
*/
22
22
 
23
 
#include "myisam_priv.h"
24
 
#include "drizzled/charset_info.h"
25
 
#include <drizzled/util/test.h>
26
 
 
27
 
using namespace std;
28
 
using namespace drizzled;
 
23
#include "myisamdef.h"
 
24
#include <mystrings/m_ctype.h>
 
25
#include <mysys/my_tree.h>
 
26
#include <mysys/queues.h>
29
27
 
30
28
        /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
31
29
 
32
30
int mi_lock_database(MI_INFO *info, int lock_type)
33
31
{
34
32
  int error;
35
 
  uint32_t count;
 
33
  uint count;
36
34
  MYISAM_SHARE *share=info->s;
37
 
  uint32_t flag;
38
 
 
39
 
  if (!info->s->in_use)
40
 
    info->s->in_use= new list<Session *>;
41
 
 
 
35
  uint flag;
 
36
 
 
37
  if (share->options & HA_OPTION_READ_ONLY_DATA ||
 
38
      info->lock_type == lock_type)
 
39
    return(0);
42
40
  if (lock_type == F_EXTRA_LCK)                 /* Used by TMP tables */
43
41
  {
44
42
    ++share->w_locks;
45
43
    ++share->tot_locks;
46
44
    info->lock_type= lock_type;
47
 
    info->s->in_use->push_front(info->in_use);
 
45
    info->s->in_use= list_add(info->s->in_use, &info->in_use);
48
46
    return(0);
49
47
  }
50
48
 
51
49
  flag=error=0;
 
50
  pthread_mutex_lock(&share->intern_lock);
52
51
  if (share->kfile >= 0)                /* May only be false on windows */
53
52
  {
54
53
    switch (lock_type) {
59
58
        count= --share->w_locks;
60
59
      --share->tot_locks;
61
60
      if (info->lock_type == F_WRLCK && !share->w_locks &&
62
 
          !share->delay_key_write && flush_key_blocks(share->getKeyCache(),
 
61
          !share->delay_key_write && flush_key_blocks(share->key_cache,
63
62
                                                      share->kfile,FLUSH_KEEP))
64
63
      {
65
 
        error=errno;
 
64
        error=my_errno;
66
65
        mi_print_error(info->s, HA_ERR_CRASHED);
67
66
        mi_mark_crashed(info);          /* Mark that table must be checked */
68
67
      }
70
69
      {
71
70
        if (end_io_cache(&info->rec_cache))
72
71
        {
73
 
          error=errno;
 
72
          error=my_errno;
74
73
          mi_print_error(info->s, HA_ERR_CRASHED);
75
74
          mi_mark_crashed(info);
76
75
        }
79
78
      {
80
79
        if (share->changed && !share->w_locks)
81
80
        {
 
81
#ifdef HAVE_MMAP
82
82
    if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
83
83
        (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
84
84
    {
 
85
      if (info->s->concurrent_insert)
 
86
        rw_wrlock(&info->s->mmap_lock);
85
87
      mi_remap_file(info, info->s->state.state.data_file_length);
86
88
      info->s->nonmmaped_inserts= 0;
 
89
      if (info->s->concurrent_insert)
 
90
        rw_unlock(&info->s->mmap_lock);
87
91
    }
 
92
#endif
88
93
          share->state.process= share->last_process=share->this_process;
89
94
          share->state.unique=   info->last_unique=  info->this_unique;
90
95
          share->state.update_count= info->last_loop= ++info->this_loop;
91
96
          if (mi_state_info_write(share->kfile, &share->state, 1))
92
 
            error=errno;
 
97
            error=my_errno;
93
98
          share->changed=0;
94
 
          share->not_flushed=1;
 
99
          if (myisam_flush)
 
100
          {
 
101
            if (my_sync(share->kfile, MYF(0)))
 
102
              error= my_errno;
 
103
            if (my_sync(info->dfile, MYF(0)))
 
104
              error= my_errno;
 
105
          }
 
106
          else
 
107
            share->not_flushed=1;
95
108
          if (error)
96
109
          {
97
110
            mi_print_error(info->s, HA_ERR_CRASHED);
112
125
      }
113
126
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
114
127
      info->lock_type= F_UNLCK;
115
 
      info->s->in_use->remove(info->in_use);
 
128
      info->s->in_use= list_delete(info->s->in_use, &info->in_use);
116
129
      break;
117
130
    case F_RDLCK:
118
131
      if (info->lock_type == F_WRLCK)
137
150
        flag=1;
138
151
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
139
152
        {
140
 
          error=errno;
 
153
          error=my_errno;
141
154
          break;
142
155
        }
143
156
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
144
157
        {
145
 
          error=errno;
146
 
          errno=error;
 
158
          error=my_errno;
 
159
          my_errno=error;
147
160
          break;
148
161
        }
149
162
      }
150
 
      _mi_test_if_changed(info);
 
163
      VOID(_mi_test_if_changed(info));
151
164
      share->r_locks++;
152
165
      share->tot_locks++;
153
166
      info->lock_type=lock_type;
154
 
      info->s->in_use->push_front(info->in_use);
 
167
      info->s->in_use= list_add(info->s->in_use, &info->in_use);
155
168
      break;
156
169
    case F_WRLCK:
157
170
      if (info->lock_type == F_RDLCK)
174
187
          {
175
188
            if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
176
189
            {
177
 
              error=errno;
178
 
              errno=error;
 
190
              error=my_errno;
 
191
              my_errno=error;
179
192
              break;
180
193
            }
181
194
          }
182
195
        }
183
196
      }
184
 
      _mi_test_if_changed(info);
185
 
 
 
197
      VOID(_mi_test_if_changed(info));
 
198
        
186
199
      info->lock_type=lock_type;
 
200
      info->invalidator=info->s->invalidator;
187
201
      share->w_locks++;
188
202
      share->tot_locks++;
189
 
      info->s->in_use->push_front(info->in_use);
 
203
      info->s->in_use= list_add(info->s->in_use, &info->in_use);
190
204
      break;
191
205
    default:
192
206
      break;                            /* Impossible */
198
212
    /*
199
213
       Check for bad file descriptors if this table is part
200
214
       of a merge union. Failing to capture this may cause
201
 
       a crash on windows if the table is renamed and
 
215
       a crash on windows if the table is renamed and 
202
216
       later on referenced by the merge table.
203
217
     */
204
218
    if( info->owned_by_merge && (info->s)->kfile < 0 )
207
221
    }
208
222
  }
209
223
#endif
 
224
  pthread_mutex_unlock(&share->intern_lock);
210
225
#if defined(FULL_LOG) || defined(_lint)
211
226
  lock_type|=(int) (flag << 8);         /* Set bit to set if real lock */
212
 
  myisam_log_command(MI_LOG_LOCK,info,(unsigned char*) &lock_type,sizeof(lock_type),
 
227
  myisam_log_command(MI_LOG_LOCK,info,(uchar*) &lock_type,sizeof(lock_type),
213
228
                     error);
214
229
#endif
215
230
  return(error);
217
232
 
218
233
 
219
234
/****************************************************************************
 
235
  The following functions are called by thr_lock() in threaded applications
 
236
****************************************************************************/
 
237
 
 
238
/*
 
239
  Create a copy of the current status for the table
 
240
 
 
241
  SYNOPSIS
 
242
    mi_get_status()
 
243
    param               Pointer to Myisam handler
 
244
    concurrent_insert   Set to 1 if we are going to do concurrent inserts
 
245
                        (THR_WRITE_CONCURRENT_INSERT was used)
 
246
*/
 
247
 
 
248
void mi_get_status(void* param, int concurrent_insert)
 
249
{
 
250
  MI_INFO *info=(MI_INFO*) param;
 
251
 
 
252
  info->save_state=info->s->state.state;
 
253
  info->state= &info->save_state;
 
254
  info->append_insert_at_end= concurrent_insert;
 
255
  return;
 
256
}
 
257
 
 
258
 
 
259
void mi_update_status(void* param)
 
260
{
 
261
  MI_INFO *info=(MI_INFO*) param;
 
262
  /*
 
263
    Because someone may have closed the table we point at, we only
 
264
    update the state if its our own state.  This isn't a problem as
 
265
    we are always pointing at our own lock or at a read lock.
 
266
    (This is enforced by thr_multi_lock.c)
 
267
  */
 
268
  if (info->state == &info->save_state)
 
269
  {
 
270
    info->s->state.state= *info->state;
 
271
    info->state= &info->s->state.state;
 
272
  }
 
273
  info->append_insert_at_end= 0;
 
274
 
 
275
  /*
 
276
    We have to flush the write cache here as other threads may start
 
277
    reading the table before mi_lock_database() is called
 
278
  */
 
279
  if (info->opt_flag & WRITE_CACHE_USED)
 
280
  {
 
281
    if (end_io_cache(&info->rec_cache))
 
282
    {
 
283
      mi_print_error(info->s, HA_ERR_CRASHED);
 
284
      mi_mark_crashed(info);
 
285
    }
 
286
    info->opt_flag&= ~WRITE_CACHE_USED;
 
287
  }
 
288
}
 
289
 
 
290
 
 
291
void mi_restore_status(void *param)
 
292
{
 
293
  MI_INFO *info= (MI_INFO*) param;
 
294
  info->state= &info->s->state.state;
 
295
  info->append_insert_at_end= 0;
 
296
}
 
297
 
 
298
 
 
299
void mi_copy_status(void* to,void *from)
 
300
{
 
301
  ((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state;
 
302
}
 
303
 
 
304
 
 
305
/*
 
306
  Check if should allow concurrent inserts
 
307
 
 
308
  IMPLEMENTATION
 
309
    Allow concurrent inserts if we don't have a hole in the table or
 
310
    if there is no active write lock and there is active read locks and 
 
311
    myisam_concurrent_insert == 2. In this last case the new
 
312
    row('s) are inserted at end of file instead of filling up the hole.
 
313
 
 
314
    The last case is to allow one to inserts into a heavily read-used table
 
315
    even if there is holes.
 
316
 
 
317
  NOTES
 
318
    If there is a an rtree indexes in the table, concurrent inserts are
 
319
    disabled in mi_open()
 
320
 
 
321
  RETURN
 
322
    0  ok to use concurrent inserts
 
323
    1  not ok
 
324
*/
 
325
 
 
326
bool mi_check_status(void *param)
 
327
{
 
328
  MI_INFO *info=(MI_INFO*) param;
 
329
  /*
 
330
    The test for w_locks == 1 is here because this thread has already done an
 
331
    external lock (in other words: w_locks == 1 means no other threads has
 
332
    a write lock)
 
333
  */
 
334
  return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
 
335
                     (myisam_concurrent_insert == 2 && info->s->r_locks &&
 
336
                      info->s->w_locks == 1));
 
337
}
 
338
 
 
339
 
 
340
/****************************************************************************
220
341
 ** functions to read / write the state
221
342
****************************************************************************/
222
343
 
229
350
    {
230
351
      if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
231
352
      {
232
 
        int error=errno ? errno : -1;
233
 
        errno=error;
 
353
        int error=my_errno ? my_errno : -1;
 
354
        my_errno=error;
234
355
        return(1);
235
356
      }
236
357
    }
237
358
    if (check_keybuffer)
238
 
      _mi_test_if_changed(info);
 
359
      VOID(_mi_test_if_changed(info));
 
360
    info->invalidator=info->s->invalidator;
239
361
  }
240
362
  else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
241
363
  {
242
 
    errno=EACCES;                               /* Not allowed to change */
 
364
    my_errno=EACCES;                            /* Not allowed to change */
243
365
    return(-1);                         /* when have read_lock() */
244
366
  }
245
367
  return(0);
251
373
  request
252
374
*/
253
375
 
254
 
int _mi_writeinfo(register MI_INFO *info, uint32_t operation)
 
376
int _mi_writeinfo(register MI_INFO *info, uint operation)
255
377
{
256
378
  int error,olderror;
257
379
  MYISAM_SHARE *share=info->s;
259
381
  error=0;
260
382
  if (share->tot_locks == 0)
261
383
  {
262
 
    olderror=errno;                     /* Remember last error */
 
384
    olderror=my_errno;                  /* Remember last error */
263
385
    if (operation)
264
386
    {                                   /* Two threads can't be here */
265
387
      share->state.process= share->last_process=   share->this_process;
266
388
      share->state.unique=  info->last_unique=     info->this_unique;
267
389
      share->state.update_count= info->last_loop= ++info->this_loop;
268
390
      if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
269
 
        olderror=errno;
 
391
        olderror=my_errno;
 
392
#ifdef __WIN__
 
393
      if (myisam_flush)
 
394
      {
 
395
        _commit(share->kfile);
 
396
        _commit(info->dfile);
 
397
      }
 
398
#endif
270
399
    }
271
 
    errno=olderror;
 
400
    my_errno=olderror;
272
401
  }
273
402
  else if (operation)
274
403
    share->changed= 1;                  /* Mark keyfile changed */
287
416
      share->state.update_count != info->last_loop)
288
417
  {                                             /* Keyfile has changed */
289
418
    if (share->state.process != share->this_process)
290
 
      flush_key_blocks(share->getKeyCache(), share->kfile, FLUSH_RELEASE);
 
419
      VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
291
420
    share->last_process=share->state.process;
292
421
    info->last_unique=  share->state.unique;
293
422
    info->last_loop=    share->state.update_count;
320
449
 
321
450
int _mi_mark_file_changed(MI_INFO *info)
322
451
{
323
 
  unsigned char buff[3];
 
452
  uchar buff[3];
324
453
  register MYISAM_SHARE *share=info->s;
325
454
 
326
455
  if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
352
481
 
353
482
int _mi_decrement_open_count(MI_INFO *info)
354
483
{
355
 
  unsigned char buff[2];
 
484
  uchar buff[2];
356
485
  register MYISAM_SHARE *share=info->s;
357
486
  int lock_error=0,write_error=0;
358
487
  if (share->global_changed)
359
488
  {
360
 
    uint32_t old_lock=info->lock_type;
 
489
    uint old_lock=info->lock_type;
361
490
    share->global_changed=0;
362
491
    lock_error=mi_lock_database(info,F_WRLCK);
363
492
    /* Its not fatal even if we couldn't get the lock ! */