~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_locking.c

  • Committer: Monty Taylor
  • Date: 2009-03-08 23:45:12 UTC
  • mto: (923.2.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 921.
  • Revision ID: mordred@inaugust.com-20090308234512-tqkygxtu1iaig23s
Removed C99 isnan() usage, which allows us to remove the util/math.{cc,h} workarounds. Yay for standards!

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
  locking of isam-tables.
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
      }
69
69
      if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
70
70
      {
71
 
        if (info->rec_cache.end_io_cache())
 
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
        pthread_rwlock_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
        pthread_rwlock_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
          }
186
200
      info->lock_type=lock_type;
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 */
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
227
  myisam_log_command(MI_LOG_LOCK,info,(unsigned char*) &lock_type,sizeof(lock_type),
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 (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
    }
239
360
  }
240
361
  else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
241
362
  {
242
 
    errno=EACCES;                               /* Not allowed to change */
 
363
    my_errno=EACCES;                            /* Not allowed to change */
243
364
    return(-1);                         /* when have read_lock() */
244
365
  }
245
366
  return(0);
259
380
  error=0;
260
381
  if (share->tot_locks == 0)
261
382
  {
262
 
    olderror=errno;                     /* Remember last error */
 
383
    olderror=my_errno;                  /* Remember last error */
263
384
    if (operation)
264
385
    {                                   /* Two threads can't be here */
265
386
      share->state.process= share->last_process=   share->this_process;
266
387
      share->state.unique=  info->last_unique=     info->this_unique;
267
388
      share->state.update_count= info->last_loop= ++info->this_loop;
268
389
      if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
269
 
        olderror=errno;
 
390
        olderror=my_errno;
 
391
#ifdef __WIN__
 
392
      if (myisam_flush)
 
393
      {
 
394
        _commit(share->kfile);
 
395
        _commit(info->dfile);
 
396
      }
 
397
#endif
270
398
    }
271
 
    errno=olderror;
 
399
    my_errno=olderror;
272
400
  }
273
401
  else if (operation)
274
402
    share->changed= 1;                  /* Mark keyfile changed */
287
415
      share->state.update_count != info->last_loop)
288
416
  {                                             /* Keyfile has changed */
289
417
    if (share->state.process != share->this_process)
290
 
      flush_key_blocks(share->getKeyCache(), share->kfile, FLUSH_RELEASE);
 
418
      flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE);
291
419
    share->last_process=share->state.process;
292
420
    info->last_unique=  share->state.unique;
293
421
    info->last_loop=    share->state.update_count;