23
#include "myisam_priv.h"
24
#include "drizzled/charset_info.h"
25
#include <drizzled/util/test.h>
29
25
/* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
31
27
int mi_lock_database(MI_INFO *info, int lock_type)
35
31
MYISAM_SHARE *share=info->s;
38
pthread_mutex_lock(&share->intern_lock);
40
info->s->in_use= new list<Session *>;
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,
38
share->global_changed, share->state.open_count,
39
share->index_file_name));
40
if (share->options & HA_OPTION_READ_ONLY_DATA ||
41
info->lock_type == lock_type)
42
43
if (lock_type == F_EXTRA_LCK) /* Used by TMP tables */
44
pthread_mutex_unlock(&share->intern_lock);
46
46
++share->tot_locks;
47
47
info->lock_type= lock_type;
48
info->s->in_use->push_front(info->in_use);
48
info->s->in_use= list_add(info->s->in_use, &info->in_use);
53
pthread_mutex_lock(&share->intern_lock);
53
54
if (share->kfile >= 0) /* May only be false on windows */
55
56
switch (lock_type) {
58
ftparser_call_deinitializer(info);
57
59
if (info->lock_type == F_RDLCK)
58
60
count= --share->r_locks;
63
65
!share->delay_key_write && flush_key_blocks(share->key_cache,
64
66
share->kfile,FLUSH_KEEP))
67
69
mi_print_error(info->s, HA_ERR_CRASHED);
68
70
mi_mark_crashed(info); /* Mark that table must be checked */
72
74
if (end_io_cache(&info->rec_cache))
75
77
mi_print_error(info->s, HA_ERR_CRASHED);
76
78
mi_mark_crashed(info);
83
DBUG_PRINT("info",("changed: %u w_locks: %u",
84
(uint) share->changed, share->w_locks));
81
85
if (share->changed && !share->w_locks)
83
88
if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
84
89
(info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
86
91
if (info->s->concurrent_insert)
87
pthread_rwlock_wrlock(&info->s->mmap_lock);
92
rw_wrlock(&info->s->mmap_lock);
88
93
mi_remap_file(info, info->s->state.state.data_file_length);
89
94
info->s->nonmmaped_inserts= 0;
90
95
if (info->s->concurrent_insert)
91
pthread_rwlock_unlock(&info->s->mmap_lock);
96
rw_unlock(&info->s->mmap_lock);
93
99
share->state.process= share->last_process=share->this_process;
94
100
share->state.unique= info->last_unique= info->this_unique;
95
101
share->state.update_count= info->last_loop= ++info->this_loop;
96
102
if (mi_state_info_write(share->kfile, &share->state, 1))
107
if (my_sync(share->kfile, MYF(0)))
109
if (my_sync(info->dfile, MYF(0)))
113
share->not_flushed=1;
102
116
mi_print_error(info->s, HA_ERR_CRASHED);
108
122
if (share->r_locks)
109
123
{ /* Only read locks left */
125
if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
126
MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
112
129
else if (!share->w_locks)
113
130
{ /* No more locks */
132
if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
133
MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
118
138
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
119
139
info->lock_type= F_UNLCK;
120
info->s->in_use->remove(info->in_use);
140
info->s->in_use= list_delete(info->s->in_use, &info->in_use);
123
143
if (info->lock_type == F_WRLCK)
140
166
if (!share->r_locks && !share->w_locks)
143
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))
148
175
if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
178
VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
155
_mi_test_if_changed(info);
183
VOID(_mi_test_if_changed(info));
156
184
share->r_locks++;
157
185
share->tot_locks++;
158
186
info->lock_type=lock_type;
159
info->s->in_use->push_front(info->in_use);
187
info->s->in_use= list_add(info->s->in_use, &info->in_use);
162
190
if (info->lock_type == F_RDLCK)
164
192
if (share->r_locks == 1)
195
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
196
MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
167
201
share->r_locks--;
168
202
share->w_locks++;
169
203
info->lock_type=lock_type;
175
209
if (!share->w_locks)
212
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
213
info->lock_wait | MY_SEEK_NOT_DONE))
178
218
if (!share->r_locks)
180
220
if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
223
VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
224
info->lock_wait | MY_SEEK_NOT_DONE));
189
_mi_test_if_changed(info);
231
VOID(_mi_test_if_changed(info));
191
233
info->lock_type=lock_type;
234
info->invalidator=info->s->invalidator;
192
235
share->w_locks++;
193
236
share->tot_locks++;
194
info->s->in_use->push_front(info->in_use);
237
info->s->in_use= list_add(info->s->in_use, &info->in_use);
197
240
break; /* Impossible */
204
247
Check for bad file descriptors if this table is part
205
248
of a merge union. Failing to capture this may cause
206
a crash on windows if the table is renamed and
249
a crash on windows if the table is renamed and
207
250
later on referenced by the merge table.
209
252
if( info->owned_by_merge && (info->s)->kfile < 0 )
215
258
pthread_mutex_unlock(&share->intern_lock);
216
259
#if defined(FULL_LOG) || defined(_lint)
217
260
lock_type|=(int) (flag << 8); /* Set bit to set if real lock */
218
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),
222
265
} /* mi_lock_database */
239
282
void mi_get_status(void* param, int concurrent_insert)
241
284
MI_INFO *info=(MI_INFO*) param;
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,
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));
243
297
info->save_state=info->s->state.state;
244
298
info->state= &info->save_state;
245
299
info->append_insert_at_end= concurrent_insert;
259
313
if (info->state == &info->save_state)
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));
261
325
info->s->state.state= *info->state;
262
326
info->state= &info->s->state.state;
300
364
Allow concurrent inserts if we don't have a hole in the table or
301
if there is no active write lock and there is active read locks and
365
if there is no active write lock and there is active read locks and
302
366
myisam_concurrent_insert == 2. In this last case the new
303
367
row('s) are inserted at end of file instead of filling up the hole.
322
386
external lock (in other words: w_locks == 1 means no other threads has
325
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 ||
326
393
(myisam_concurrent_insert == 2 && info->s->r_locks &&
327
394
info->s->w_locks == 1));
335
402
int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
404
DBUG_ENTER("_mi_readinfo");
337
406
if (info->lock_type == F_UNLCK)
339
408
MYISAM_SHARE *share=info->s;
340
409
if (!share->tot_locks)
411
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
412
info->lock_wait | MY_SEEK_NOT_DONE))
342
414
if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
344
int error=errno ? errno : -1;
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)));
349
423
if (check_keybuffer)
350
_mi_test_if_changed(info);
424
VOID(_mi_test_if_changed(info));
425
info->invalidator=info->s->invalidator;
352
427
else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
354
errno=EACCES; /* Not allowed to change */
355
return(-1); /* when have read_lock() */
429
my_errno=EACCES; /* Not allowed to change */
430
DBUG_RETURN(-1); /* when have read_lock() */
358
433
} /* _mi_readinfo */
366
int _mi_writeinfo(register MI_INFO *info, uint32_t operation)
441
int _mi_writeinfo(register MI_INFO *info, uint operation)
368
443
int error,olderror;
369
444
MYISAM_SHARE *share=info->s;
445
DBUG_ENTER("_mi_writeinfo");
446
DBUG_PRINT("info",("operation: %u tot_locks: %u", operation,
372
450
if (share->tot_locks == 0)
374
olderror=errno; /* Remember last error */
452
olderror=my_errno; /* Remember last error */
376
454
{ /* Two threads can't be here */
377
455
share->state.process= share->last_process= share->this_process;
378
456
share->state.unique= info->last_unique= info->this_unique;
379
457
share->state.update_count= info->last_loop= ++info->this_loop;
380
458
if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
463
_commit(share->kfile);
464
_commit(info->dfile);
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)
385
474
else if (operation)
386
475
share->changed= 1; /* Mark keyfile changed */
388
477
} /* _mi_writeinfo */
398
487
share->state.unique != info->last_unique ||
399
488
share->state.update_count != info->last_loop)
400
489
{ /* Keyfile has changed */
490
DBUG_PRINT("info",("index file changed"));
401
491
if (share->state.process != share->this_process)
402
flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE);
492
VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
403
493
share->last_process=share->state.process;
404
494
info->last_unique= share->state.unique;
405
495
info->last_loop= share->state.update_count;
427
517
was incremented in the same process.
429
519
This mean that if we are the only process using the file, the open_count
430
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).
433
525
int _mi_mark_file_changed(MI_INFO *info)
435
unsigned char buff[3];
436
528
register MYISAM_SHARE *share=info->s;
529
DBUG_ENTER("_mi_mark_file_changed");
438
531
if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
449
542
mi_int2store(buff,share->state.open_count);
450
543
buff[2]=1; /* Mark that it's changed */
451
return(my_pwrite(share->kfile,buff,sizeof(buff),
544
DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff),
452
545
sizeof(share->state.header),
465
558
int _mi_decrement_open_count(MI_INFO *info)
467
unsigned char buff[2];
468
561
register MYISAM_SHARE *share=info->s;
469
562
int lock_error=0,write_error=0;
470
563
if (share->global_changed)
472
uint32_t old_lock=info->lock_type;
565
uint old_lock=info->lock_type;
473
566
share->global_changed=0;
474
567
lock_error=mi_lock_database(info,F_WRLCK);
475
568
/* Its not fatal even if we couldn't get the lock ! */