1
/* Copyright (C) 2000-2005 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
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 */
16
#include "myisam_priv.h"
17
#include <drizzled/util/test.h>
18
#include <sys/types.h>
24
using namespace drizzled;
27
static void mi_extra_keyflag(MI_INFO *info, enum ha_extra_function function);
31
Set options and buffers to optimize table handling
37
extra_arg Pointer to extra argument (normally pointer to uint32_t)
38
Used when function is one of:
46
int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
50
MYISAM_SHARE *share=info->s;
53
case HA_EXTRA_RESET_STATE: /* Reset state (don't free buffers) */
54
info->lastinx= 0; /* Use first index as def */
55
info->last_search_keypage=info->lastpos= HA_OFFSET_ERROR;
57
/* Next/prev gives first/last */
58
if (info->opt_flag & READ_CACHE_USED)
60
info->rec_cache.reinit_io_cache(internal::READ_CACHE,0,
61
(bool) (info->lock_type != F_UNLCK),
62
(bool) test(info->update & HA_STATE_ROW_CHANGED));
64
info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
68
if (info->lock_type == F_UNLCK &&
69
(share->options & HA_OPTION_PACK_RECORD))
71
error=1; /* Not possibly if not locked */
75
if (info->s->file_map) /* Don't use cache if mmap */
77
if (info->opt_flag & WRITE_CACHE_USED)
79
info->opt_flag&= ~WRITE_CACHE_USED;
80
if ((error= info->rec_cache.end_io_cache()))
83
if (!(info->opt_flag &
84
(READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
86
cache_size= (extra_arg ? *(uint32_t*) extra_arg :
87
internal::my_default_record_cache_size);
88
if (!(info->rec_cache.init_io_cache(info->dfile, (uint) min((uint32_t)info->state->data_file_length+1, cache_size),
89
internal::READ_CACHE,0L,(bool) (info->lock_type != F_UNLCK),
90
MYF(share->write_flag & MY_WAIT_IF_FULL))))
92
info->opt_flag|=READ_CACHE_USED;
93
info->update&= ~HA_STATE_ROW_CHANGED;
95
if (share->concurrent_insert)
96
info->rec_cache.end_of_file=info->state->data_file_length;
99
case HA_EXTRA_REINIT_CACHE:
100
if (info->opt_flag & READ_CACHE_USED)
102
info->rec_cache.reinit_io_cache(internal::READ_CACHE,info->nextpos,
103
(bool) (info->lock_type != F_UNLCK),
104
(bool) test(info->update & HA_STATE_ROW_CHANGED));
105
info->update&= ~HA_STATE_ROW_CHANGED;
106
if (share->concurrent_insert)
107
info->rec_cache.end_of_file=info->state->data_file_length;
110
case HA_EXTRA_WRITE_CACHE:
111
if (info->lock_type == F_UNLCK)
113
error=1; /* Not possibly if not locked */
117
cache_size= (extra_arg ? *(uint32_t*) extra_arg :
118
internal::my_default_record_cache_size);
119
if (not (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) && !share->state.header.uniques)
121
if (not (info->rec_cache.init_io_cache(info->dfile, cache_size,
122
internal::WRITE_CACHE,info->state->data_file_length,
123
(bool) (info->lock_type != F_UNLCK),
124
MYF(share->write_flag & MY_WAIT_IF_FULL))))
126
info->opt_flag|=WRITE_CACHE_USED;
127
info->update&= ~(HA_STATE_ROW_CHANGED |
128
HA_STATE_WRITE_AT_END |
129
HA_STATE_EXTEND_BLOCK);
133
case HA_EXTRA_PREPARE_FOR_UPDATE:
134
if (info->s->data_file_type != DYNAMIC_RECORD)
136
/* Remove read/write cache if dynamic rows */
137
case HA_EXTRA_NO_CACHE:
138
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
140
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
141
error= info->rec_cache.end_io_cache();
142
/* Sergei will insert full text index caching here */
144
#if !defined(TARGET_OS_SOLARIS)
145
if (info->opt_flag & MEMMAP_USED)
146
madvise((char*) share->file_map, share->state.state.data_file_length,
150
case HA_EXTRA_FLUSH_CACHE:
151
if (info->opt_flag & WRITE_CACHE_USED)
153
if ((error=flush_io_cache(&info->rec_cache)))
155
mi_print_error(info->s, HA_ERR_CRASHED);
156
mi_mark_crashed(info); /* Fatal error found */
160
case HA_EXTRA_NO_READCHECK:
161
info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
163
case HA_EXTRA_READCHECK:
164
info->opt_flag|= READ_CHECK_USED;
166
case HA_EXTRA_KEYREAD: /* Read only keys to record */
167
case HA_EXTRA_REMEMBER_POS:
168
info->opt_flag |= REMEMBER_OLD_POS;
169
memmove(info->lastkey+share->base.max_key_length*2,
170
info->lastkey,info->lastkey_length);
171
info->save_update= info->update;
172
info->save_lastinx= info->lastinx;
173
info->save_lastpos= info->lastpos;
174
info->save_lastkey_length=info->lastkey_length;
175
if (function == HA_EXTRA_REMEMBER_POS)
178
case HA_EXTRA_KEYREAD_CHANGE_POS:
179
info->opt_flag |= KEY_READ_USED;
180
info->read_record=_mi_read_key_record;
182
case HA_EXTRA_NO_KEYREAD:
183
case HA_EXTRA_RESTORE_POS:
184
if (info->opt_flag & REMEMBER_OLD_POS)
186
memmove(info->lastkey,
187
info->lastkey+share->base.max_key_length*2,
188
info->save_lastkey_length);
189
info->update= info->save_update | HA_STATE_WRITTEN;
190
info->lastinx= info->save_lastinx;
191
info->lastpos= info->save_lastpos;
192
info->lastkey_length=info->save_lastkey_length;
194
info->read_record= share->read_record;
195
info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
197
case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
198
info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
200
case HA_EXTRA_WAIT_LOCK:
203
case HA_EXTRA_NO_WAIT_LOCK:
204
info->lock_wait=MY_DONT_WAIT;
206
case HA_EXTRA_NO_KEYS:
207
if (info->lock_type == F_UNLCK)
209
error=1; /* Not possibly if not lock */
212
if (mi_is_any_key_active(share->state.key_map))
214
MI_KEYDEF *key=share->keyinfo;
216
for (i=0 ; i < share->base.keys ; i++,key++)
218
if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
220
mi_clear_key_active(share->state.key_map, i);
221
info->update|= HA_STATE_CHANGED;
227
share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
228
share->changed=1; /* Update on close */
229
if (!share->global_changed)
231
share->global_changed=1;
232
share->state.open_count++;
235
share->state.state= *info->state;
236
error=mi_state_info_write(share->kfile,&share->state,1 | 2);
239
case HA_EXTRA_FORCE_REOPEN:
240
THR_LOCK_myisam.lock();
241
share->last_version= 0L; /* Impossible version */
242
THR_LOCK_myisam.unlock();
244
case HA_EXTRA_PREPARE_FOR_DROP:
245
THR_LOCK_myisam.lock();
246
share->last_version= 0L; /* Impossible version */
247
#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND
248
/* Close the isam and data files as Win32 can't drop an open table */
249
if (flush_key_blocks(share->key_cache, share->kfile,
250
(function == HA_EXTRA_FORCE_REOPEN ?
251
FLUSH_RELEASE : FLUSH_IGNORE_CHANGED)))
255
mi_print_error(info->s, HA_ERR_CRASHED);
256
mi_mark_crashed(info); /* Fatal error found */
258
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
260
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
261
error=end_io_cache(&info->rec_cache);
263
if (info->lock_type != F_UNLCK && ! info->was_locked)
265
info->was_locked=info->lock_type;
266
if (mi_lock_database(info,F_UNLCK))
268
info->lock_type = F_UNLCK;
270
if (share->kfile >= 0)
271
_mi_decrement_open_count(info);
272
if (share->kfile >= 0 && internal::my_close(share->kfile,MYF(0)))
275
list<MI_INFO *>::iterator it= myisam_open_list.begin();
276
while (it != myisam_open_list.end())
278
MI_INFO *tmpinfo= *it;
279
if (tmpinfo->s == info->s)
281
if (tmpinfo->dfile >= 0 && internal::my_close(tmpinfo->dfile,MYF(0)))
288
share->kfile= -1; /* Files aren't open anymore */
290
THR_LOCK_myisam.unlock();
293
if (!share->temporary)
294
flush_key_blocks(share->getKeyCache(), share->kfile, FLUSH_KEEP);
296
_mi_decrement_open_count(info);
298
if (share->not_flushed)
300
share->not_flushed= false;
302
if (share->base.blobs)
303
mi_alloc_rec_buff(info, SIZE_MAX, &info->rec_buff);
305
case HA_EXTRA_NORMAL: /* Theese isn't in use */
311
case HA_EXTRA_NO_ROWS:
312
if (!share->state.header.uniques)
313
info->opt_flag|= OPT_NO_ROWS;
315
case HA_EXTRA_PRELOAD_BUFFER_SIZE:
316
info->preload_buff_size= *((uint32_t *) extra_arg);
318
case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
319
case HA_EXTRA_CHANGE_KEY_TO_DUP:
320
mi_extra_keyflag(info, function);
322
case HA_EXTRA_KEY_CACHE:
323
case HA_EXTRA_NO_KEY_CACHE:
333
Start/Stop Inserting Duplicates Into a Table, WL#1648.
335
static void mi_extra_keyflag(MI_INFO *info, enum ha_extra_function function)
339
for (idx= 0; idx< info->s->base.keys; idx++)
342
case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
343
info->s->keyinfo[idx].flag|= HA_NOSAME;
345
case HA_EXTRA_CHANGE_KEY_TO_DUP:
346
info->s->keyinfo[idx].flag&= ~(HA_NOSAME);
355
int mi_reset(MI_INFO *info)
358
MYISAM_SHARE *share=info->s;
360
Free buffers and reset the following flags:
361
EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
363
If the row buffer cache is large (for dynamic tables), reduce it
366
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
368
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
369
error= info->rec_cache.end_io_cache();
371
if (share->base.blobs)
372
mi_alloc_rec_buff(info, SIZE_MAX, &info->rec_buff);
373
#if !defined(TARGET_OS_SOLARIS)
374
if (info->opt_flag & MEMMAP_USED)
375
madvise((char*) share->file_map, share->state.state.data_file_length,
378
info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
380
info->lastinx= 0; /* Use first index as def */
381
info->last_search_keypage= info->lastpos= HA_OFFSET_ERROR;
382
info->page_changed= 1;
383
info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
384
HA_STATE_PREV_FOUND);