~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_locking.c

  • Committer: Monty Taylor
  • Date: 2008-10-23 00:05:28 UTC
  • Revision ID: monty@inaugust.com-20081023000528-grdvrd8c4058nutm
Moved my_handler to myisam, which is where it actually belongs.

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