home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / isam / _locking.c < prev    next >
C/C++ Source or Header  |  2000-08-31  |  9KB  |  346 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. /*
  18.   locking of isam-tables.
  19.   reads info from a isam-table. Must be first request before doing any furter
  20.   calls to any isamfunktion.  Is used to allow many process use the same
  21.   isamdatabase.
  22.   */
  23.  
  24. #include "isamdef.h"
  25. #ifdef    __WIN__
  26. #include <errno.h>
  27. #endif
  28.  
  29.     /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
  30.  
  31. int nisam_lock_database(N_INFO *info, int lock_type)
  32. {
  33.   int error;
  34.   uint count;
  35.   ISAM_SHARE *share;
  36.   uint flag;
  37.   DBUG_ENTER("nisam_lock_database");
  38.  
  39.   flag=error=0;
  40. #ifndef NO_LOCKING
  41.   share=info->s;
  42.   if (share->base.options & HA_OPTION_READ_ONLY_DATA ||
  43.       info->lock_type == lock_type)
  44.     DBUG_RETURN(0);
  45.   pthread_mutex_lock(&share->intern_lock);
  46.   switch (lock_type) {
  47.   case F_UNLCK:
  48.     if (info->lock_type == F_RDLCK)
  49.       count= --share->r_locks;
  50.     else
  51.       count= --share->w_locks;
  52.     if (info->lock_type == F_WRLCK && !share->w_locks &&
  53.     flush_key_blocks(share->kfile,FLUSH_KEEP))
  54.       error=my_errno;
  55.     if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  56.       if (end_io_cache(&info->rec_cache))
  57.     error=my_errno;
  58.  
  59.     if (!count)
  60.     {
  61.       if (share->changed && !share->w_locks)
  62.       {
  63.     share->state.process= share->last_process=share->this_process;
  64.     share->state.loop=    info->last_loop=        ++info->this_loop;
  65.     share->state.uniq=    info->last_uniq=        info->this_uniq;
  66.     if (my_pwrite(share->kfile,(char*) &share->state.header,
  67.               share->state_length,0L,MYF(MY_NABP)))
  68.       error=my_errno;
  69.     share->changed=0;
  70. #ifdef __WIN__
  71.     if (nisam_flush)
  72.     {
  73.       _commit(share->kfile);
  74.       _commit(info->dfile);
  75.     }
  76.     else
  77.       share->not_flushed=1;
  78. #endif
  79.       }
  80.       if (share->r_locks)
  81.       {                    /* Only read locks left */
  82.     flag=1;
  83.     if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
  84.             MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
  85.       error=my_errno;
  86.       }
  87.       else if (!share->w_locks)
  88.       {                    /* No more locks */
  89.     flag=1;
  90.     if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
  91.             MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
  92.       error=my_errno;
  93.       }
  94.     }
  95.     info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  96.     info->lock_type= F_UNLCK;
  97.     break;
  98.   case F_RDLCK:
  99.     if (info->lock_type == F_WRLCK)
  100.     {                        /* Change RW to READONLY */
  101.       if (share->w_locks == 1)
  102.       {
  103.     flag=1;
  104.     if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
  105.             MYF(MY_SEEK_NOT_DONE)))
  106.     {
  107.       error=my_errno;
  108.       break;
  109.     }
  110.       }
  111.       share->w_locks--;
  112.       share->r_locks++;
  113.       info->lock_type=lock_type;
  114.       break;
  115.     }
  116.     if (!share->r_locks && !share->w_locks)
  117.     {
  118.       flag=1;
  119. #ifdef HAVE_FCNTL
  120.       if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  121.       {
  122.     error=my_errno;
  123.     break;
  124.       }
  125.       if (my_pread(share->kfile,
  126.            (char*) &share->state.header,share->state_length,0L,
  127.            MYF(MY_NABP)))
  128.       {
  129.     error=my_errno;
  130.     VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
  131.     my_errno=error;
  132.     break;
  133.       }
  134. #else
  135.       VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
  136.       if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  137.       {
  138.     error=my_errno;
  139.     break;
  140.       }
  141.       if (my_read(share->kfile,
  142.           (char*) &share->state.header,share->state_length,
  143.           MYF(MY_NABP)))
  144.       {
  145.     error=my_errno;
  146.     VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
  147.     my_errno=error;
  148.     break;
  149.       }
  150. #endif
  151.     }
  152.     VOID(_nisam_test_if_changed(info));
  153.     share->r_locks++;
  154.     info->lock_type=lock_type;
  155.     break;
  156.   case F_WRLCK:
  157.     if (info->lock_type == F_RDLCK)
  158.     {                        /* Change RW to READONLY */
  159.       if (share->r_locks == 1)
  160.       {
  161.     flag=1;
  162.     if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
  163.             MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
  164.     {
  165.       error=my_errno;
  166.       break;
  167.     }
  168.     share->r_locks--;
  169.     share->w_locks++;
  170.     info->lock_type=lock_type;
  171.     break;
  172.       }
  173.     }
  174.     if (!(share->base.options & HA_OPTION_READ_ONLY_DATA) && !share->w_locks)
  175.     {
  176.       flag=1;
  177.       VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
  178.       if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  179.       {
  180.     error=my_errno;
  181.     break;
  182.       }
  183.       if (!share->r_locks)
  184.       {
  185.     if (my_read(share->kfile,
  186.             (char*) &share->state.header,share->state_length,
  187.             MYF(MY_NABP)))
  188.     {
  189.       error=my_errno;
  190.       VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
  191.       my_errno=error;
  192.       break;
  193.     }
  194.       }
  195.     }
  196.     VOID(_nisam_test_if_changed(info));
  197.     info->lock_type=lock_type;
  198.     share->w_locks++;
  199.     break;
  200.   default:
  201.     break;                /* Impossible */
  202.   }
  203.   pthread_mutex_unlock(&share->intern_lock);
  204. #if defined(FULL_LOG) || defined(_lint)
  205.   lock_type|=(int) (flag << 8);        /* Set bit to set if real lock */
  206.   nisam_log_command(LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type),
  207.             error);
  208. #endif
  209. #endif
  210.   DBUG_RETURN(error);
  211. } /* nisam_lock_database */
  212.  
  213.  
  214.     /* Is used before access to database is granted */
  215.  
  216. int _nisam_readinfo(register N_INFO *info, int lock_type, int check_keybuffer)
  217. {
  218.   ISAM_SHARE *share;
  219.   DBUG_ENTER("_nisam_readinfo");
  220.  
  221.   share=info->s;
  222.   if (info->lock_type == F_UNLCK)
  223.   {
  224.     if (!share->r_locks && !share->w_locks)
  225.     {
  226. #ifndef HAVE_FCNTL
  227.       VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
  228. #endif
  229. #ifndef NO_LOCKING
  230. #ifdef UNSAFE_LOCKING
  231.       if ((info->tmp_lock_type=lock_type) != F_RDLCK)
  232. #endif
  233.     if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  234.       DBUG_RETURN(1);
  235. #endif
  236. #ifdef HAVE_FCNTL
  237.       if (my_pread(share->kfile,
  238.           (char*) &share->state.header,share->state_length,0L,
  239.           MYF(MY_NABP)))
  240. #else
  241.       if (my_read(share->kfile,
  242.           (char*) &share->state.header,share->state_length,
  243.           MYF(MY_NABP)))
  244. #endif
  245.       {
  246. #ifndef NO_LOCKING
  247.     int error=my_errno;
  248.     VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
  249.              MYF(MY_SEEK_NOT_DONE)));
  250.     my_errno=error;
  251. #endif
  252.     DBUG_RETURN(1);
  253.       }
  254.     }
  255.     if (check_keybuffer)
  256.       VOID(_nisam_test_if_changed(info));
  257.   }
  258.   else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
  259.   {
  260.     my_errno=EACCES;                /* Not allowed to change */
  261.     DBUG_RETURN(-1);                /* when have read_lock() */
  262.   }
  263.   DBUG_RETURN(0);
  264. } /* _nisam_readinfo */
  265.  
  266.  
  267.     /* Every isam-function that uppdates the isam-database must! end */
  268.     /* with this request */
  269.     /* ARGSUSED */
  270.  
  271. int _nisam_writeinfo(register N_INFO *info, uint flags)
  272. {
  273.   int error,olderror;
  274.   ISAM_SHARE *share;
  275.   DBUG_ENTER("_nisam_writeinfo");
  276.  
  277.   error=0;
  278.   share=info->s;
  279.   if (share->r_locks == 0 && share->w_locks == 0)
  280.   {
  281.     olderror=my_errno;            /* Remember last error */
  282.     if (flags)
  283.     {                    /* Two threads can't be here */
  284.       share->state.process= share->last_process=   share->this_process;
  285.       share->state.loop=    info->last_loop=        ++info->this_loop;
  286.       share->state.uniq=    info->last_uniq=       info->this_uniq;
  287.       if ((error=my_pwrite(share->kfile,(char*) &share->state.header,
  288.                share->state_length,0L,MYF(MY_NABP)) != 0))
  289.     olderror=my_errno;
  290. #ifdef __WIN__
  291.       if (nisam_flush)
  292.       {
  293.     _commit(share->kfile);
  294.     _commit(info->dfile);
  295.       }
  296. #endif
  297.     }
  298.     if (flags != 2)
  299.     {
  300. #ifndef NO_LOCKING
  301. #ifdef UNSAFE_LOCKING
  302.       if (info->tmp_lock_type != F_RDLCK)
  303. #endif
  304.       {
  305.     if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
  306.             MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
  307.       DBUG_RETURN(1);
  308.       }
  309.     }
  310. #endif
  311.     my_errno=olderror;
  312.   }
  313.   else if (flags)
  314.     share->changed= 1;            /* Mark keyfile changed */
  315.   DBUG_RETURN(error);
  316. } /* _nisam_writeinfo */
  317.  
  318.  
  319.     /* Test if someone has changed the database */
  320.     /* (Should be called after readinfo) */
  321.  
  322. int _nisam_test_if_changed(register N_INFO *info)
  323. {
  324. #ifndef NO_LOCKING
  325.   {
  326.     ISAM_SHARE *share=info->s;
  327.     if (share->state.process != share->last_process ||
  328.     share->state.loop    != info->last_loop ||
  329.     share->state.uniq    != info->last_uniq)
  330.     {                        /* Keyfile has changed */
  331.       if (share->state.process != share->this_process)
  332.     VOID(flush_key_blocks(share->kfile,FLUSH_RELEASE));
  333.       share->last_process=share->state.process;
  334.       info->last_loop=    share->state.loop;
  335.       info->last_uniq=    share->state.uniq;
  336.       info->update|=    HA_STATE_WRITTEN;    /* Must use file on next */
  337.       info->data_changed= 1;            /* For nisam_is_changed */
  338.       return 1;
  339.     }
  340.   }
  341. #endif
  342.   return (!(info->update & HA_STATE_AKTIV) ||
  343.       (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
  344.                HA_STATE_KEY_CHANGED)));
  345. } /* _nisam_test_if_changed */
  346.