Drizzled Public API Documentation

mi_extra.cc
1 /* Copyright (C) 2000-2005 MySQL AB
2 
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.
6 
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.
11 
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 */
15 
16 #include "myisam_priv.h"
17 #include <drizzled/util/test.h>
18 #include <sys/types.h>
19 #include <sys/mman.h>
20 
21 #include <string.h>
22 #include <algorithm>
23 
24 using namespace drizzled;
25 using namespace std;
26 
27 static void mi_extra_keyflag(MI_INFO *info, enum ha_extra_function function);
28 
29 
30 /*
31  Set options and buffers to optimize table handling
32 
33  SYNOPSIS
34  mi_extra()
35  info open table
36  function operation
37  extra_arg Pointer to extra argument (normally pointer to uint32_t)
38  Used when function is one of:
39  HA_EXTRA_WRITE_CACHE
40  HA_EXTRA_CACHE
41  RETURN VALUES
42  0 ok
43  # error
44 */
45 
46 int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
47 {
48  int error=0;
49  uint32_t cache_size;
50  MYISAM_SHARE *share=info->s;
51 
52  switch (function) {
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;
56  info->page_changed=1;
57  /* Next/prev gives first/last */
58  if (info->opt_flag & READ_CACHE_USED)
59  {
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));
63  }
64  info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
65  HA_STATE_PREV_FOUND);
66  break;
67  case HA_EXTRA_CACHE:
68  if (info->lock_type == F_UNLCK &&
69  (share->options & HA_OPTION_PACK_RECORD))
70  {
71  error=1; /* Not possibly if not locked */
72  errno=EACCES;
73  break;
74  }
75  if (info->s->file_map) /* Don't use cache if mmap */
76  break;
77  if (info->opt_flag & WRITE_CACHE_USED)
78  {
79  info->opt_flag&= ~WRITE_CACHE_USED;
80  if ((error= info->rec_cache.end_io_cache()))
81  break;
82  }
83  if (!(info->opt_flag &
84  (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
85  {
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))))
91  {
92  info->opt_flag|=READ_CACHE_USED;
93  info->update&= ~HA_STATE_ROW_CHANGED;
94  }
95  if (share->concurrent_insert)
96  info->rec_cache.end_of_file=info->state->data_file_length;
97  }
98  break;
99  case HA_EXTRA_REINIT_CACHE:
100  if (info->opt_flag & READ_CACHE_USED)
101  {
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;
108  }
109  break;
110  case HA_EXTRA_WRITE_CACHE:
111  if (info->lock_type == F_UNLCK)
112  {
113  error=1; /* Not possibly if not locked */
114  break;
115  }
116 
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)
120  {
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))))
125  {
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);
130  }
131  }
132  break;
133  case HA_EXTRA_PREPARE_FOR_UPDATE:
134  if (info->s->data_file_type != DYNAMIC_RECORD)
135  break;
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))
139  {
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 */
143  }
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,
147  MADV_RANDOM);
148 #endif
149  break;
150  case HA_EXTRA_FLUSH_CACHE:
151  if (info->opt_flag & WRITE_CACHE_USED)
152  {
153  if ((error= info->rec_cache.flush()))
154  {
155  mi_print_error(info->s, HA_ERR_CRASHED);
156  mi_mark_crashed(info); /* Fatal error found */
157  }
158  }
159  break;
160  case HA_EXTRA_NO_READCHECK:
161  info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
162  break;
163  case HA_EXTRA_READCHECK:
164  info->opt_flag|= READ_CHECK_USED;
165  break;
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)
176  break;
177  /* fall through */
178  case HA_EXTRA_KEYREAD_CHANGE_POS:
179  info->opt_flag |= KEY_READ_USED;
180  info->read_record=_mi_read_key_record;
181  break;
182  case HA_EXTRA_NO_KEYREAD:
183  case HA_EXTRA_RESTORE_POS:
184  if (info->opt_flag & REMEMBER_OLD_POS)
185  {
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;
193  }
194  info->read_record= share->read_record;
195  info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
196  break;
197  case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
198  info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
199  break;
200  case HA_EXTRA_WAIT_LOCK:
201  info->lock_wait=0;
202  break;
203  case HA_EXTRA_NO_WAIT_LOCK:
204  info->lock_wait=MY_DONT_WAIT;
205  break;
206  case HA_EXTRA_NO_KEYS:
207  if (info->lock_type == F_UNLCK)
208  {
209  error=1; /* Not possibly if not lock */
210  break;
211  }
212  if (mi_is_any_key_active(share->state.key_map))
213  {
214  MI_KEYDEF *key=share->keyinfo;
215  uint32_t i;
216  for (i=0 ; i < share->base.keys ; i++,key++)
217  {
218  if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
219  {
220  mi_clear_key_active(share->state.key_map, i);
221  info->update|= HA_STATE_CHANGED;
222  }
223  }
224 
225  if (!share->changed)
226  {
227  share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
228  share->changed=1; /* Update on close */
229  if (!share->global_changed)
230  {
231  share->global_changed=1;
232  share->state.open_count++;
233  }
234  }
235  share->state.state= *info->state;
236  error=mi_state_info_write(share->kfile,&share->state,1 | 2);
237  }
238  break;
239  case HA_EXTRA_FORCE_REOPEN:
240  THR_LOCK_myisam.lock();
241  share->last_version= 0L; /* Impossible version */
242  THR_LOCK_myisam.unlock();
243  break;
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 (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
250  {
251  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
252  error=end_io_cache(&info->rec_cache);
253  }
254  if (info->lock_type != F_UNLCK && ! info->was_locked)
255  {
256  info->was_locked=info->lock_type;
257  if (mi_lock_database(info,F_UNLCK))
258  error=errno;
259  info->lock_type = F_UNLCK;
260  }
261  if (share->kfile >= 0)
262  _mi_decrement_open_count(info);
263  if (share->kfile >= 0 && internal::my_close(share->kfile,MYF(0)))
264  error=errno;
265  {
266  list<MI_INFO *>::iterator it= myisam_open_list.begin();
267  while (it != myisam_open_list.end())
268  {
269  MI_INFO *tmpinfo= *it;
270  if (tmpinfo->s == info->s)
271  {
272  if (tmpinfo->dfile >= 0 && internal::my_close(tmpinfo->dfile,MYF(0)))
273  error = errno;
274  tmpinfo->dfile= -1;
275  }
276  ++it;
277  }
278  }
279  share->kfile= -1; /* Files aren't open anymore */
280 #endif
281  THR_LOCK_myisam.unlock();
282  break;
283  case HA_EXTRA_FLUSH:
284 #ifdef HAVE_PWRITE
285  _mi_decrement_open_count(info);
286 #endif
287  if (share->not_flushed)
288  {
289  share->not_flushed= false;
290  }
291  if (share->base.blobs)
292  mi_alloc_rec_buff(info, SIZE_MAX, &info->rec_buff);
293  break;
294  case HA_EXTRA_NORMAL: /* Theese isn't in use */
295  info->quick_mode=0;
296  break;
297  case HA_EXTRA_QUICK:
298  info->quick_mode=1;
299  break;
300  case HA_EXTRA_NO_ROWS:
301  if (!share->state.header.uniques)
302  info->opt_flag|= OPT_NO_ROWS;
303  break;
304  case HA_EXTRA_PRELOAD_BUFFER_SIZE:
305  info->preload_buff_size= *((uint32_t *) extra_arg);
306  break;
307  case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
308  case HA_EXTRA_CHANGE_KEY_TO_DUP:
309  mi_extra_keyflag(info, function);
310  break;
311  case HA_EXTRA_KEY_CACHE:
312  case HA_EXTRA_NO_KEY_CACHE:
313  default:
314  break;
315  }
316 
317  return(error);
318 } /* mi_extra */
319 
320 
321 /*
322  Start/Stop Inserting Duplicates Into a Table, WL#1648.
323  */
324 static void mi_extra_keyflag(MI_INFO *info, enum ha_extra_function function)
325 {
326  uint32_t idx;
327 
328  for (idx= 0; idx< info->s->base.keys; idx++)
329  {
330  switch (function) {
331  case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
332  info->s->keyinfo[idx].flag|= HA_NOSAME;
333  break;
334  case HA_EXTRA_CHANGE_KEY_TO_DUP:
335  info->s->keyinfo[idx].flag&= ~(HA_NOSAME);
336  break;
337  default:
338  break;
339  }
340  }
341 }
342 
343 
344 int mi_reset(MI_INFO *info)
345 {
346  int error= 0;
347  MYISAM_SHARE *share=info->s;
348  /*
349  Free buffers and reset the following flags:
350  EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
351 
352  If the row buffer cache is large (for dynamic tables), reduce it
353  to save memory.
354  */
355  if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
356  {
357  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
358  error= info->rec_cache.end_io_cache();
359  }
360  if (share->base.blobs)
361  mi_alloc_rec_buff(info, SIZE_MAX, &info->rec_buff);
362 #if !defined(TARGET_OS_SOLARIS)
363  if (info->opt_flag & MEMMAP_USED)
364  madvise((char*) share->file_map, share->state.state.data_file_length,
365  MADV_RANDOM);
366 #endif
367  info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
368  info->quick_mode=0;
369  info->lastinx= 0; /* Use first index as def */
370  info->last_search_keypage= info->lastpos= HA_OFFSET_ERROR;
371  info->page_changed= 1;
372  info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
373  HA_STATE_PREV_FOUND);
374  return(error);
375 }
TODO: Rename this file - func.h is stupid.
int init_io_cache(int file, size_t cachesize, cache_type type, my_off_t seek_offset, bool use_async_io, myf cache_myflags)
Initialize an io_cache_st object.
Definition: mf_iocache.cc:174
int end_io_cache()
Free an io_cache_st object.
Definition: mf_iocache.cc:685
bool reinit_io_cache(cache_type type_arg, my_off_t seek_offset, bool use_async_io, bool clear_cache)
Reset the cache.
Definition: mf_iocache.cc:280