home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / myisam / mi_extra.c < prev    next >
C/C++ Source or Header  |  2000-10-15  |  11KB  |  345 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17. /* Extra functions we want to do with a database */
  18. /* - Set flags for quicker databasehandler */
  19. /* - Set databasehandler to normal */
  20. /* - Reset recordpointers as after open database */
  21.  
  22. #include "myisamdef.h"
  23. #ifdef HAVE_MMAP
  24. #include <sys/mman.h>
  25. #endif
  26. #ifdef    __WIN__
  27. #include <errno.h>
  28. #endif
  29.  
  30.     /* set extra flags for database */
  31.  
  32. int mi_extra(MI_INFO *info, enum ha_extra_function function)
  33. {
  34.   int error=0;
  35.   MYISAM_SHARE *share=info->s;
  36.   DBUG_ENTER("mi_extra");
  37.  
  38.   switch (function) {
  39.   case HA_EXTRA_RESET:
  40.     /*
  41.       Free buffers and reset the following flags:
  42.       EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
  43.     */
  44.     if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  45.     {
  46.       info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  47.       error=end_io_cache(&info->rec_cache);
  48.     }
  49. #if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
  50.     if (info->opt_flag & MEMMAP_USED)
  51.       madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
  52. #endif
  53.     info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);    
  54.     info->quick_mode=0;
  55.     /* Fall through */
  56.  
  57.   case HA_EXTRA_RESET_STATE:        /* Reset state (don't free buffers) */
  58.     info->lastinx= 0;            /* Use first index as def */
  59.     info->last_search_keypage=info->lastpos= HA_OFFSET_ERROR;
  60.     info->page_changed=1;
  61.                     /* Next/prev gives first/last */
  62.     if (info->opt_flag & READ_CACHE_USED)
  63.     {
  64.       reinit_io_cache(&info->rec_cache,READ_CACHE,0,
  65.               (pbool) (info->lock_type != F_UNLCK),
  66.               (pbool) test(info->update & HA_STATE_ROW_CHANGED)
  67.               );
  68.     }
  69.     info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
  70.            HA_STATE_PREV_FOUND);
  71.     break;
  72.   case HA_EXTRA_CACHE:
  73.     if (info->lock_type == F_UNLCK &&
  74.     (share->options & HA_OPTION_PACK_RECORD))
  75.     {
  76.       error=1;            /* Not possibly if not locked */
  77.       my_errno=EACCES;
  78.       break;
  79.     }
  80. #if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
  81.     if ((share->options & HA_OPTION_COMPRESS_RECORD))
  82.     {
  83.       pthread_mutex_lock(&share->intern_lock);
  84.       if (_mi_memmap_file(info))
  85.       {
  86.     /* We don't nead MADV_SEQUENTIAL if small file */
  87.     madvise(share->file_map,share->state.state.data_file_length,
  88.         share->state.state.data_file_length <= RECORD_CACHE_SIZE*16 ?
  89.         MADV_RANDOM : MADV_SEQUENTIAL);
  90.     pthread_mutex_unlock(&share->intern_lock);
  91.     break;
  92.       }
  93.       pthread_mutex_unlock(&share->intern_lock);
  94.     }
  95. #endif
  96.     if (info->opt_flag & WRITE_CACHE_USED)
  97.     {
  98.       info->opt_flag&= ~WRITE_CACHE_USED;
  99.       if ((error=end_io_cache(&info->rec_cache)))
  100.     break;
  101.     }
  102.     if (!(info->opt_flag &
  103.       (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
  104.     {
  105.       if (!(init_io_cache(&info->rec_cache,info->dfile,
  106.              (uint) min(info->state->data_file_length+1,
  107.                     my_default_record_cache_size),
  108.              READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
  109.              MYF(share->write_flag & MY_WAIT_IF_FULL))))
  110.       {
  111.     info->opt_flag|=READ_CACHE_USED;
  112.     info->update&= ~HA_STATE_ROW_CHANGED;
  113.       }
  114.       if (share->concurrent_insert)
  115.     info->rec_cache.end_of_file=info->state->data_file_length;
  116.     }
  117.     break;
  118.   case HA_EXTRA_REINIT_CACHE:
  119.     if (info->opt_flag & READ_CACHE_USED)
  120.     {
  121.       reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos,
  122.               (pbool) (info->lock_type != F_UNLCK),
  123.               (pbool) test(info->update & HA_STATE_ROW_CHANGED));
  124.       info->update&= ~HA_STATE_ROW_CHANGED;
  125.       if (share->concurrent_insert)
  126.     info->rec_cache.end_of_file=info->state->data_file_length;
  127.     }
  128.     break;
  129.   case HA_EXTRA_WRITE_CACHE:
  130.     if (info->lock_type == F_UNLCK)
  131.     {
  132.       error=1;            /* Not possibly if not locked */
  133.       break;
  134.     }
  135.     if (!(info->opt_flag &
  136.       (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
  137.     !share->state.header.uniques)
  138.       if (!(init_io_cache(&info->rec_cache,info->dfile,0,
  139.              WRITE_CACHE,info->state->data_file_length,
  140.               (pbool) (info->lock_type != F_UNLCK),
  141.               MYF(share->write_flag & MY_WAIT_IF_FULL))))
  142.       {
  143.     info->opt_flag|=WRITE_CACHE_USED;
  144.     info->update&= ~(HA_STATE_ROW_CHANGED |
  145.              HA_STATE_WRITE_AT_END |
  146.              HA_STATE_EXTEND_BLOCK);
  147.       }
  148.     break;
  149.   case HA_EXTRA_NO_CACHE:
  150.     if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  151.     {
  152.       info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  153.       error=end_io_cache(&info->rec_cache);
  154.     }
  155. #if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
  156.     if (info->opt_flag & MEMMAP_USED)
  157.       madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
  158. #endif
  159.     break;
  160.   case HA_EXTRA_FLUSH_CACHE:
  161.     if (info->opt_flag & WRITE_CACHE_USED)
  162.     {
  163.       if ((error=flush_io_cache(&info->rec_cache)))
  164.     mi_mark_crashed(info);            /* Fatal error found */
  165.     }
  166.     break;
  167.   case HA_EXTRA_NO_READCHECK:
  168.     info->opt_flag&= ~READ_CHECK_USED;        /* No readcheck */
  169.     break;
  170.   case HA_EXTRA_READCHECK:
  171.     info->opt_flag|= READ_CHECK_USED;
  172.     break;
  173.   case HA_EXTRA_KEYREAD:            /* Read only keys to record */
  174.   case HA_EXTRA_REMEMBER_POS:
  175.     info->opt_flag |= REMEMBER_OLD_POS;
  176.     bmove((byte*) info->lastkey+share->base.max_key_length*2,
  177.       (byte*) info->lastkey,info->lastkey_length);
  178.     info->save_update=    info->update;
  179.     info->save_lastinx= info->lastinx;
  180.     info->save_lastpos= info->lastpos;
  181.     info->save_lastkey_length=info->lastkey_length;
  182.     if (function == HA_EXTRA_REMEMBER_POS)
  183.       break;
  184.     /* fall through */
  185.   case HA_EXTRA_KEYREAD_CHANGE_POS:
  186.     info->opt_flag |= KEY_READ_USED;
  187.     info->read_record=_mi_read_key_record;
  188.     break;
  189.   case HA_EXTRA_NO_KEYREAD:
  190.   case HA_EXTRA_RESTORE_POS:
  191.     if (info->opt_flag & REMEMBER_OLD_POS)
  192.     {
  193.       bmove((byte*) info->lastkey,
  194.         (byte*) info->lastkey+share->base.max_key_length*2,
  195.         info->save_lastkey_length);
  196.       info->update=    info->save_update | HA_STATE_WRITTEN;
  197.       info->lastinx=    info->save_lastinx;
  198.       info->lastpos=    info->save_lastpos;
  199.       info->lastkey_length=info->save_lastkey_length;
  200.     }
  201.     info->read_record=    share->read_record;
  202.     info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
  203.     break;
  204.   case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
  205.     info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
  206.     break;
  207.   case HA_EXTRA_WAIT_LOCK:
  208.     info->lock_wait=0;
  209.     break;
  210.   case HA_EXTRA_NO_WAIT_LOCK:
  211.     info->lock_wait=MY_DONT_WAIT;
  212.     break;
  213.   case HA_EXTRA_NO_KEYS:
  214.     if (info->lock_type == F_UNLCK)
  215.     {
  216.       error=1;                    /* Not possibly if not lock */
  217.       break;
  218.     }
  219.     if (share->state.key_map)
  220.     {
  221.       share->state.key_map=0;
  222.       info->state->key_file_length=share->state.state.key_file_length=
  223.     share->base.keystart;
  224.       if (!share->changed)
  225.       {
  226.     share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
  227.     share->changed=1;            /* Update on close */
  228.     if (!share->global_changed)
  229.     {
  230.       share->global_changed=1;
  231.       share->state.open_count++;
  232.     }
  233.       }
  234.       share->state.state= *info->state;
  235.       error=mi_state_info_write(share->kfile,&share->state,1 | 2);
  236.     }
  237.     break;
  238.   case HA_EXTRA_FORCE_REOPEN:
  239.     pthread_mutex_lock(&THR_LOCK_myisam);
  240.     share->last_version= 0L;            /* Impossible version */
  241. #ifdef __WIN__
  242.     /* Close the isam and data files as Win32 can't drop an open table */
  243.     pthread_mutex_lock(&share->intern_lock);
  244.     if (flush_key_blocks(share->kfile,FLUSH_RELEASE))
  245.     {
  246.       error=my_errno;
  247.       share->changed=1;
  248.       mi_mark_crashed(info);            /* Fatal error found */
  249.     }
  250.     if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  251.     {
  252.       info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  253.       error=end_io_cache(&info->rec_cache);
  254.     }
  255.     if (info->lock_type != F_UNLCK && ! info->was_locked)
  256.     {
  257.       info->was_locked=info->lock_type;
  258.       if (mi_lock_database(info,F_UNLCK))
  259.     error=my_errno;
  260.       info->lock_type = F_UNLCK;
  261.     }
  262.     if (share->kfile >= 0)
  263.       _mi_decrement_open_count(info);
  264.     if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
  265.       error=my_errno;
  266.     {
  267.       LIST *list_element ;
  268.       for (list_element=myisam_open_list ;
  269.        list_element ;
  270.        list_element=list_element->next)
  271.       {
  272.     MI_INFO *tmpinfo=(MI_INFO*) list_element->data;
  273.     if (tmpinfo->s == info->s)
  274.     {
  275.       if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile,MYF(0)))
  276.         error = my_errno;
  277.       tmpinfo->dfile= -1;
  278.     }
  279.       }
  280.     }
  281.     share->kfile= -1;                /* Files aren't open anymore */
  282.     pthread_mutex_unlock(&share->intern_lock);
  283. #endif
  284.     pthread_mutex_unlock(&THR_LOCK_myisam);
  285.     break;
  286.   case HA_EXTRA_FLUSH:
  287.     if (!share->temporary)
  288.       flush_key_blocks(share->kfile,FLUSH_KEEP);
  289. #ifdef HAVE_PWRITE
  290.     _mi_decrement_open_count(info);
  291. #endif
  292.     if (share->not_flushed)
  293.     {
  294.       share->not_flushed=0;
  295. #if defined(__WIN__)
  296.       if (_commit(share->kfile))
  297.     error=errno;
  298.       if (_commit(info->dfile))
  299.     error=errno;
  300. #elif defined(HAVE_FDATASYNC)
  301.       if (fdatasync(share->kfile))
  302.     error=errno;
  303.       if (fdatasync(share->dfile))
  304.     error=errno;
  305. #elif defined(HAVE_FSYNC)
  306.       if ( fsync(share->kfile))
  307.     error=errno;
  308.       if (fsync(share->dfile))
  309.     error=errno;
  310. #endif
  311.       if (error)
  312.       {
  313.     share->changed=1;
  314.     mi_mark_crashed(info);            /* Fatal error found */
  315.       }
  316.     }
  317.     if (share->base.blobs)
  318.     {
  319.       my_free(info->rec_alloc,MYF(MY_ALLOW_ZERO_PTR));
  320.       info->rec_alloc=info->rec_buff=0;
  321.     }
  322.     break;
  323.   case HA_EXTRA_NORMAL:                /* Theese isn't in use */
  324.     info->quick_mode=0;
  325.     break;
  326.   case HA_EXTRA_QUICK:
  327.     info->quick_mode=1;
  328.     break;
  329.   case HA_EXTRA_NO_ROWS:
  330.     if (!share->state.header.uniques)
  331.       info->opt_flag|= OPT_NO_ROWS;
  332.     break;
  333.   case HA_EXTRA_KEY_CACHE:
  334.   case HA_EXTRA_NO_KEY_CACHE:
  335.   default:
  336.     break;
  337.   }
  338.   {
  339.     char tmp[1];
  340.     tmp[0]=function;
  341.     myisam_log_command(MI_LOG_EXTRA,info,(byte*) tmp,1,error);
  342.   }
  343.   DBUG_RETURN(error);
  344. } /* mi_extra */
  345.