~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_locking.c

  • Committer: Brian Aker
  • Date: 2008-07-03 00:14:39 UTC
  • Revision ID: brian@tangent.org-20080703001439-pit0mcl0wk8elxlq
Cleanup of sql-common and mysqldump

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
  isamdatabase.
21
21
*/
22
22
 
23
 
#include "myisamdef.h"
24
 
#include <mystrings/m_ctype.h>
25
 
#include <mysys/my_tree.h>
26
 
#include <mysys/queues.h>
 
23
#include "ftdefs.h"
27
24
 
28
25
        /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
29
26
 
30
27
int mi_lock_database(MI_INFO *info, int lock_type)
31
28
{
32
29
  int error;
33
 
  uint32_t count;
 
30
  uint count;
34
31
  MYISAM_SHARE *share=info->s;
35
 
  uint32_t flag;
36
 
 
 
32
  uint flag;
 
33
  DBUG_ENTER("mi_lock_database");
 
34
  DBUG_PRINT("enter",("lock_type: %d  old lock %d  r_locks: %u  w_locks: %u "
 
35
                      "global_changed:  %d  open_count: %u  name: '%s'",
 
36
                      lock_type, info->lock_type, share->r_locks,
 
37
                      share->w_locks,
 
38
                      share->global_changed, share->state.open_count,
 
39
                      share->index_file_name));
37
40
  if (share->options & HA_OPTION_READ_ONLY_DATA ||
38
41
      info->lock_type == lock_type)
39
 
    return(0);
 
42
    DBUG_RETURN(0);
40
43
  if (lock_type == F_EXTRA_LCK)                 /* Used by TMP tables */
41
44
  {
42
45
    ++share->w_locks;
43
46
    ++share->tot_locks;
44
47
    info->lock_type= lock_type;
45
48
    info->s->in_use= list_add(info->s->in_use, &info->in_use);
46
 
    return(0);
 
49
    DBUG_RETURN(0);
47
50
  }
48
51
 
49
52
  flag=error=0;
52
55
  {
53
56
    switch (lock_type) {
54
57
    case F_UNLCK:
 
58
      ftparser_call_deinitializer(info);
55
59
      if (info->lock_type == F_RDLCK)
56
60
        count= --share->r_locks;
57
61
      else
76
80
      }
77
81
      if (!count)
78
82
      {
 
83
        DBUG_PRINT("info",("changed: %u  w_locks: %u",
 
84
                           (uint) share->changed, share->w_locks));
79
85
        if (share->changed && !share->w_locks)
80
86
        {
81
87
#ifdef HAVE_MMAP
116
122
          if (share->r_locks)
117
123
          {                                     /* Only read locks left */
118
124
            flag=1;
 
125
            if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
 
126
                        MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
 
127
              error=my_errno;
119
128
          }
120
129
          else if (!share->w_locks)
121
130
          {                                     /* No more locks */
122
131
            flag=1;
 
132
            if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
133
                        MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
 
134
              error=my_errno;
123
135
          }
124
136
        }
125
137
      }
139
151
        if (share->w_locks == 1)
140
152
        {
141
153
          flag=1;
 
154
          if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
155
                      MYF(MY_SEEK_NOT_DONE)))
 
156
          {
 
157
            error=my_errno;
 
158
            break;
 
159
          }
142
160
        }
143
161
        share->w_locks--;
144
162
        share->r_locks++;
148
166
      if (!share->r_locks && !share->w_locks)
149
167
      {
150
168
        flag=1;
151
 
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
 
169
        if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
170
                    info->lock_wait | MY_SEEK_NOT_DONE))
152
171
        {
153
172
          error=my_errno;
154
173
          break;
156
175
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
157
176
        {
158
177
          error=my_errno;
 
178
          VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
159
179
          my_errno=error;
160
180
          break;
161
181
        }
162
182
      }
163
 
      _mi_test_if_changed(info);
 
183
      VOID(_mi_test_if_changed(info));
164
184
      share->r_locks++;
165
185
      share->tot_locks++;
166
186
      info->lock_type=lock_type;
172
192
        if (share->r_locks == 1)
173
193
        {
174
194
          flag=1;
 
195
          if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
196
                      MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
 
197
          {
 
198
            error=my_errno;
 
199
            break;
 
200
          }
175
201
          share->r_locks--;
176
202
          share->w_locks++;
177
203
          info->lock_type=lock_type;
183
209
        if (!share->w_locks)
184
210
        {
185
211
          flag=1;
 
212
          if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
213
                      info->lock_wait | MY_SEEK_NOT_DONE))
 
214
          {
 
215
            error=my_errno;
 
216
            break;
 
217
          }
186
218
          if (!share->r_locks)
187
219
          {
188
220
            if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
189
221
            {
190
222
              error=my_errno;
 
223
              VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
224
                           info->lock_wait | MY_SEEK_NOT_DONE));
191
225
              my_errno=error;
192
226
              break;
193
227
            }
194
228
          }
195
229
        }
196
230
      }
197
 
      _mi_test_if_changed(info);
 
231
      VOID(_mi_test_if_changed(info));
198
232
        
199
233
      info->lock_type=lock_type;
200
234
      info->invalidator=info->s->invalidator;
224
258
  pthread_mutex_unlock(&share->intern_lock);
225
259
#if defined(FULL_LOG) || defined(_lint)
226
260
  lock_type|=(int) (flag << 8);         /* Set bit to set if real lock */
227
 
  myisam_log_command(MI_LOG_LOCK,info,(unsigned char*) &lock_type,sizeof(lock_type),
 
261
  myisam_log_command(MI_LOG_LOCK,info,(uchar*) &lock_type,sizeof(lock_type),
228
262
                     error);
229
263
#endif
230
 
  return(error);
 
264
  DBUG_RETURN(error);
231
265
} /* mi_lock_database */
232
266
 
233
267
 
248
282
void mi_get_status(void* param, int concurrent_insert)
249
283
{
250
284
  MI_INFO *info=(MI_INFO*) param;
251
 
 
 
285
  DBUG_ENTER("mi_get_status");
 
286
  DBUG_PRINT("info",("key_file: %ld  data_file: %ld  concurrent_insert: %d",
 
287
                     (long) info->s->state.state.key_file_length,
 
288
                     (long) info->s->state.state.data_file_length,
 
289
                     concurrent_insert));
 
290
#ifndef DBUG_OFF
 
291
  if (info->state->key_file_length > info->s->state.state.key_file_length ||
 
292
      info->state->data_file_length > info->s->state.state.data_file_length)
 
293
    DBUG_PRINT("warning",("old info:  key_file: %ld  data_file: %ld",
 
294
                          (long) info->state->key_file_length,
 
295
                          (long) info->state->data_file_length));
 
296
#endif
252
297
  info->save_state=info->s->state.state;
253
298
  info->state= &info->save_state;
254
299
  info->append_insert_at_end= concurrent_insert;
255
 
  return;
 
300
  DBUG_VOID_RETURN;
256
301
}
257
302
 
258
303
 
267
312
  */
268
313
  if (info->state == &info->save_state)
269
314
  {
 
315
#ifndef DBUG_OFF
 
316
    DBUG_PRINT("info",("updating status:  key_file: %ld  data_file: %ld",
 
317
                       (long) info->state->key_file_length,
 
318
                       (long) info->state->data_file_length));
 
319
    if (info->state->key_file_length < info->s->state.state.key_file_length ||
 
320
        info->state->data_file_length < info->s->state.state.data_file_length)
 
321
      DBUG_PRINT("warning",("old info:  key_file: %ld  data_file: %ld",
 
322
                            (long) info->s->state.state.key_file_length,
 
323
                            (long) info->s->state.state.data_file_length));
 
324
#endif
270
325
    info->s->state.state= *info->state;
271
326
    info->state= &info->s->state.state;
272
327
  }
323
378
    1  not ok
324
379
*/
325
380
 
326
 
bool mi_check_status(void *param)
 
381
my_bool mi_check_status(void *param)
327
382
{
328
383
  MI_INFO *info=(MI_INFO*) param;
329
384
  /*
331
386
    external lock (in other words: w_locks == 1 means no other threads has
332
387
    a write lock)
333
388
  */
334
 
  return (bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
 
389
  DBUG_PRINT("info",("dellink: %ld  r_locks: %u  w_locks: %u",
 
390
                     (long) info->s->state.dellink, (uint) info->s->r_locks,
 
391
                     (uint) info->s->w_locks));
 
392
  return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
335
393
                     (myisam_concurrent_insert == 2 && info->s->r_locks &&
336
394
                      info->s->w_locks == 1));
337
395
}
343
401
 
344
402
int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
345
403
{
 
404
  DBUG_ENTER("_mi_readinfo");
 
405
 
346
406
  if (info->lock_type == F_UNLCK)
347
407
  {
348
408
    MYISAM_SHARE *share=info->s;
349
409
    if (!share->tot_locks)
350
410
    {
 
411
      if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
 
412
                  info->lock_wait | MY_SEEK_NOT_DONE))
 
413
        DBUG_RETURN(1);
351
414
      if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
352
415
      {
353
416
        int error=my_errno ? my_errno : -1;
 
417
        VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
418
                     MYF(MY_SEEK_NOT_DONE)));
354
419
        my_errno=error;
355
 
        return(1);
 
420
        DBUG_RETURN(1);
356
421
      }
357
422
    }
358
423
    if (check_keybuffer)
359
 
      _mi_test_if_changed(info);
 
424
      VOID(_mi_test_if_changed(info));
360
425
    info->invalidator=info->s->invalidator;
361
426
  }
362
427
  else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
363
428
  {
364
429
    my_errno=EACCES;                            /* Not allowed to change */
365
 
    return(-1);                         /* when have read_lock() */
 
430
    DBUG_RETURN(-1);                            /* when have read_lock() */
366
431
  }
367
 
  return(0);
 
432
  DBUG_RETURN(0);
368
433
} /* _mi_readinfo */
369
434
 
370
435
 
373
438
  request
374
439
*/
375
440
 
376
 
int _mi_writeinfo(register MI_INFO *info, uint32_t operation)
 
441
int _mi_writeinfo(register MI_INFO *info, uint operation)
377
442
{
378
443
  int error,olderror;
379
444
  MYISAM_SHARE *share=info->s;
 
445
  DBUG_ENTER("_mi_writeinfo");
 
446
  DBUG_PRINT("info",("operation: %u  tot_locks: %u", operation,
 
447
                     share->tot_locks));
380
448
 
381
449
  error=0;
382
450
  if (share->tot_locks == 0)
397
465
      }
398
466
#endif
399
467
    }
 
468
    if (!(operation & WRITEINFO_NO_UNLOCK) &&
 
469
        my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
 
470
                MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
 
471
      DBUG_RETURN(1);
400
472
    my_errno=olderror;
401
473
  }
402
474
  else if (operation)
403
475
    share->changed= 1;                  /* Mark keyfile changed */
404
 
  return(error);
 
476
  DBUG_RETURN(error);
405
477
} /* _mi_writeinfo */
406
478
 
407
479
 
415
487
      share->state.unique  != info->last_unique ||
416
488
      share->state.update_count != info->last_loop)
417
489
  {                                             /* Keyfile has changed */
 
490
    DBUG_PRINT("info",("index file changed"));
418
491
    if (share->state.process != share->this_process)
419
 
      flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE);
 
492
      VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
420
493
    share->last_process=share->state.process;
421
494
    info->last_unique=  share->state.unique;
422
495
    info->last_loop=    share->state.update_count;
444
517
    was incremented in the same process.
445
518
 
446
519
  This mean that if we are the only process using the file, the open_count
447
 
  tells us if the MYISAM file wasn't properly closed.*/
 
520
  tells us if the MYISAM file wasn't properly closed. (This is true if
 
521
  my_disable_locking is set).
 
522
*/
448
523
 
449
524
 
450
525
int _mi_mark_file_changed(MI_INFO *info)
451
526
{
452
 
  unsigned char buff[3];
 
527
  uchar buff[3];
453
528
  register MYISAM_SHARE *share=info->s;
 
529
  DBUG_ENTER("_mi_mark_file_changed");
454
530
 
455
531
  if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
456
532
  {
465
541
    {
466
542
      mi_int2store(buff,share->state.open_count);
467
543
      buff[2]=1;                                /* Mark that it's changed */
468
 
      return(my_pwrite(share->kfile,buff,sizeof(buff),
 
544
      DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff),
469
545
                            sizeof(share->state.header),
470
546
                            MYF(MY_NABP)));
471
547
    }
472
548
  }
473
 
  return(0);
 
549
  DBUG_RETURN(0);
474
550
}
475
551
 
476
552
 
481
557
 
482
558
int _mi_decrement_open_count(MI_INFO *info)
483
559
{
484
 
  unsigned char buff[2];
 
560
  uchar buff[2];
485
561
  register MYISAM_SHARE *share=info->s;
486
562
  int lock_error=0,write_error=0;
487
563
  if (share->global_changed)
488
564
  {
489
 
    uint32_t old_lock=info->lock_type;
 
565
    uint old_lock=info->lock_type;
490
566
    share->global_changed=0;
491
567
    lock_error=mi_lock_database(info,F_WRLCK);
492
568
    /* Its not fatal even if we couldn't get the lock ! */