~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/mi_locking.cc

Merged in latest plugin-slot-reorg.

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>
25
26
#include <drizzled/util/test.h>
26
27
 
27
28
using namespace std;
28
 
using namespace drizzled;
29
29
 
30
30
        /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
31
31
 
36
36
  MYISAM_SHARE *share=info->s;
37
37
  uint32_t flag;
38
38
 
 
39
  pthread_mutex_lock(&share->intern_lock);
39
40
  if (!info->s->in_use)
40
41
    info->s->in_use= new list<Session *>;
41
42
 
42
43
  if (lock_type == F_EXTRA_LCK)                 /* Used by TMP tables */
43
44
  {
 
45
    pthread_mutex_unlock(&share->intern_lock);
44
46
    ++share->w_locks;
45
47
    ++share->tot_locks;
46
48
    info->lock_type= lock_type;
59
61
        count= --share->w_locks;
60
62
      --share->tot_locks;
61
63
      if (info->lock_type == F_WRLCK && !share->w_locks &&
62
 
          !share->delay_key_write && flush_key_blocks(share->getKeyCache(),
 
64
          !share->delay_key_write && flush_key_blocks(share->key_cache,
63
65
                                                      share->kfile,FLUSH_KEEP))
64
66
      {
65
 
        error=errno;
 
67
        error=my_errno;
66
68
        mi_print_error(info->s, HA_ERR_CRASHED);
67
69
        mi_mark_crashed(info);          /* Mark that table must be checked */
68
70
      }
69
71
      if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
70
72
      {
71
 
        if (info->rec_cache.end_io_cache())
 
73
        if (end_io_cache(&info->rec_cache))
72
74
        {
73
 
          error=errno;
 
75
          error=my_errno;
74
76
          mi_print_error(info->s, HA_ERR_CRASHED);
75
77
          mi_mark_crashed(info);
76
78
        }
79
81
      {
80
82
        if (share->changed && !share->w_locks)
81
83
        {
 
84
#ifdef HAVE_MMAP
82
85
    if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
83
86
        (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
84
87
    {
 
88
      if (info->s->concurrent_insert)
 
89
        pthread_rwlock_wrlock(&info->s->mmap_lock);
85
90
      mi_remap_file(info, info->s->state.state.data_file_length);
86
91
      info->s->nonmmaped_inserts= 0;
 
92
      if (info->s->concurrent_insert)
 
93
        pthread_rwlock_unlock(&info->s->mmap_lock);
87
94
    }
 
95
#endif
88
96
          share->state.process= share->last_process=share->this_process;
89
97
          share->state.unique=   info->last_unique=  info->this_unique;
90
98
          share->state.update_count= info->last_loop= ++info->this_loop;
91
99
          if (mi_state_info_write(share->kfile, &share->state, 1))
92
 
            error=errno;
 
100
            error=my_errno;
93
101
          share->changed=0;
94
102
          share->not_flushed=1;
95
103
          if (error)
137
145
        flag=1;
138
146
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
139
147
        {
140
 
          error=errno;
 
148
          error=my_errno;
141
149
          break;
142
150
        }
143
151
        if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
144
152
        {
145
 
          error=errno;
146
 
          errno=error;
 
153
          error=my_errno;
 
154
          my_errno=error;
147
155
          break;
148
156
        }
149
157
      }
174
182
          {
175
183
            if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
176
184
            {
177
 
              error=errno;
178
 
              errno=error;
 
185
              error=my_errno;
 
186
              my_errno=error;
179
187
              break;
180
188
            }
181
189
          }
207
215
    }
208
216
  }
209
217
#endif
 
218
  pthread_mutex_unlock(&share->intern_lock);
210
219
#if defined(FULL_LOG) || defined(_lint)
211
220
  lock_type|=(int) (flag << 8);         /* Set bit to set if real lock */
212
221
  myisam_log_command(MI_LOG_LOCK,info,(unsigned char*) &lock_type,sizeof(lock_type),
217
226
 
218
227
 
219
228
/****************************************************************************
 
229
  The following functions are called by thr_lock() in threaded applications
 
230
****************************************************************************/
 
231
 
 
232
/*
 
233
  Create a copy of the current status for the table
 
234
 
 
235
  SYNOPSIS
 
236
    mi_get_status()
 
237
    param               Pointer to Myisam handler
 
238
    concurrent_insert   Set to 1 if we are going to do concurrent inserts
 
239
                        (THR_WRITE_CONCURRENT_INSERT was used)
 
240
*/
 
241
 
 
242
void mi_get_status(void* param, int concurrent_insert)
 
243
{
 
244
  MI_INFO *info=(MI_INFO*) param;
 
245
 
 
246
  info->save_state=info->s->state.state;
 
247
  info->state= &info->save_state;
 
248
  info->append_insert_at_end= concurrent_insert;
 
249
  return;
 
250
}
 
251
 
 
252
 
 
253
void mi_update_status(void* param)
 
254
{
 
255
  MI_INFO *info=(MI_INFO*) param;
 
256
  /*
 
257
    Because someone may have closed the table we point at, we only
 
258
    update the state if its our own state.  This isn't a problem as
 
259
    we are always pointing at our own lock or at a read lock.
 
260
    (This is enforced by thr_multi_lock.c)
 
261
  */
 
262
  if (info->state == &info->save_state)
 
263
  {
 
264
    info->s->state.state= *info->state;
 
265
    info->state= &info->s->state.state;
 
266
  }
 
267
  info->append_insert_at_end= 0;
 
268
 
 
269
  /*
 
270
    We have to flush the write cache here as other threads may start
 
271
    reading the table before mi_lock_database() is called
 
272
  */
 
273
  if (info->opt_flag & WRITE_CACHE_USED)
 
274
  {
 
275
    if (end_io_cache(&info->rec_cache))
 
276
    {
 
277
      mi_print_error(info->s, HA_ERR_CRASHED);
 
278
      mi_mark_crashed(info);
 
279
    }
 
280
    info->opt_flag&= ~WRITE_CACHE_USED;
 
281
  }
 
282
}
 
283
 
 
284
 
 
285
void mi_restore_status(void *param)
 
286
{
 
287
  MI_INFO *info= (MI_INFO*) param;
 
288
  info->state= &info->s->state.state;
 
289
  info->append_insert_at_end= 0;
 
290
}
 
291
 
 
292
 
 
293
void mi_copy_status(void* to,void *from)
 
294
{
 
295
  ((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state;
 
296
}
 
297
 
 
298
 
 
299
/*
 
300
  Check if should allow concurrent inserts
 
301
 
 
302
  IMPLEMENTATION
 
303
    Allow concurrent inserts if we don't have a hole in the table or
 
304
    if there is no active write lock and there is active read locks and
 
305
    myisam_concurrent_insert == 2. In this last case the new
 
306
    row('s) are inserted at end of file instead of filling up the hole.
 
307
 
 
308
    The last case is to allow one to inserts into a heavily read-used table
 
309
    even if there is holes.
 
310
 
 
311
  NOTES
 
312
    If there is a an rtree indexes in the table, concurrent inserts are
 
313
    disabled in mi_open()
 
314
 
 
315
  RETURN
 
316
    0  ok to use concurrent inserts
 
317
    1  not ok
 
318
*/
 
319
 
 
320
bool mi_check_status(void *param)
 
321
{
 
322
  MI_INFO *info=(MI_INFO*) param;
 
323
  /*
 
324
    The test for w_locks == 1 is here because this thread has already done an
 
325
    external lock (in other words: w_locks == 1 means no other threads has
 
326
    a write lock)
 
327
  */
 
328
  return (bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
 
329
                     (myisam_concurrent_insert == 2 && info->s->r_locks &&
 
330
                      info->s->w_locks == 1));
 
331
}
 
332
 
 
333
 
 
334
/****************************************************************************
220
335
 ** functions to read / write the state
221
336
****************************************************************************/
222
337
 
229
344
    {
230
345
      if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
231
346
      {
232
 
        int error=errno ? errno : -1;
233
 
        errno=error;
 
347
        int error=my_errno ? my_errno : -1;
 
348
        my_errno=error;
234
349
        return(1);
235
350
      }
236
351
    }
239
354
  }
240
355
  else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
241
356
  {
242
 
    errno=EACCES;                               /* Not allowed to change */
 
357
    my_errno=EACCES;                            /* Not allowed to change */
243
358
    return(-1);                         /* when have read_lock() */
244
359
  }
245
360
  return(0);
259
374
  error=0;
260
375
  if (share->tot_locks == 0)
261
376
  {
262
 
    olderror=errno;                     /* Remember last error */
 
377
    olderror=my_errno;                  /* Remember last error */
263
378
    if (operation)
264
379
    {                                   /* Two threads can't be here */
265
380
      share->state.process= share->last_process=   share->this_process;
266
381
      share->state.unique=  info->last_unique=     info->this_unique;
267
382
      share->state.update_count= info->last_loop= ++info->this_loop;
268
383
      if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
269
 
        olderror=errno;
 
384
        olderror=my_errno;
270
385
    }
271
 
    errno=olderror;
 
386
    my_errno=olderror;
272
387
  }
273
388
  else if (operation)
274
389
    share->changed= 1;                  /* Mark keyfile changed */
287
402
      share->state.update_count != info->last_loop)
288
403
  {                                             /* Keyfile has changed */
289
404
    if (share->state.process != share->this_process)
290
 
      flush_key_blocks(share->getKeyCache(), share->kfile, FLUSH_RELEASE);
 
405
      flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE);
291
406
    share->last_process=share->state.process;
292
407
    info->last_unique=  share->state.unique;
293
408
    info->last_loop=    share->state.update_count;