_locking.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   locking of isam-tables.
  15.   reads info from a isam-table. Must be first request before doing any furter
  16.   calls to any isamfunktion.  Is used to allow many process use the same
  17.   isamdatabase.
  18.   */
  19. #include "isamdef.h"
  20. #ifdef __WIN__
  21. #include <errno.h>
  22. #endif
  23. /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
  24. int nisam_lock_database(N_INFO *info, int lock_type)
  25. {
  26.   int error;
  27.   uint count;
  28.   ISAM_SHARE *share;
  29.   uint flag;
  30.   DBUG_ENTER("nisam_lock_database");
  31.   flag=error=0;
  32. #ifndef NO_LOCKING
  33.   share=info->s;
  34.   if (share->base.options & HA_OPTION_READ_ONLY_DATA ||
  35.       info->lock_type == lock_type)
  36.     DBUG_RETURN(0);
  37.   pthread_mutex_lock(&share->intern_lock);
  38.   switch (lock_type) {
  39.   case F_UNLCK:
  40.     if (info->lock_type == F_RDLCK)
  41.       count= --share->r_locks;
  42.     else
  43.       count= --share->w_locks;
  44.     if (info->lock_type == F_WRLCK && !share->w_locks &&
  45. flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_KEEP))
  46.       error=my_errno;
  47.     if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  48.       if (end_io_cache(&info->rec_cache))
  49. error=my_errno;
  50.     if (!count)
  51.     {
  52.       if (share->changed && !share->w_locks)
  53.       {
  54. share->state.process= share->last_process=share->this_process;
  55. share->state.loop=    info->last_loop=     ++info->this_loop;
  56. share->state.uniq=    info->last_uniq=     info->this_uniq;
  57. if (my_pwrite(share->kfile,(char*) &share->state.header,
  58.       share->state_length,0L,MYF(MY_NABP)))
  59.   error=my_errno;
  60. share->changed=0;
  61. #ifdef __WIN__
  62. if (nisam_flush)
  63. {
  64.   _commit(share->kfile);
  65.   _commit(info->dfile);
  66. }
  67. else
  68.   share->not_flushed=1;
  69. #endif
  70.       }
  71.       if (share->r_locks)
  72.       { /* Only read locks left */
  73. flag=1;
  74. if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
  75.     MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
  76.   error=my_errno;
  77.       }
  78.       else if (!share->w_locks)
  79.       { /* No more locks */
  80. flag=1;
  81. if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
  82.     MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
  83.   error=my_errno;
  84.       }
  85.     }
  86.     info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  87.     info->lock_type= F_UNLCK;
  88.     break;
  89.   case F_RDLCK:
  90.     if (info->lock_type == F_WRLCK)
  91.     { /* Change RW to READONLY */
  92.       if (share->w_locks == 1)
  93.       {
  94. flag=1;
  95. if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
  96.     MYF(MY_SEEK_NOT_DONE)))
  97. {
  98.   error=my_errno;
  99.   break;
  100. }
  101.       }
  102.       share->w_locks--;
  103.       share->r_locks++;
  104.       info->lock_type=lock_type;
  105.       break;
  106.     }
  107.     if (!share->r_locks && !share->w_locks)
  108.     {
  109.       flag=1;
  110. #ifdef HAVE_FCNTL
  111.       if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  112.       {
  113. error=my_errno;
  114. break;
  115.       }
  116.       if (my_pread(share->kfile,
  117.    (char*) &share->state.header,share->state_length,0L,
  118.    MYF(MY_NABP)))
  119.       {
  120. error=my_errno;
  121. VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
  122. my_errno=error;
  123. break;
  124.       }
  125. #else
  126.       VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
  127.       if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  128.       {
  129. error=my_errno;
  130. break;
  131.       }
  132.       if (my_read(share->kfile,
  133.   (char*) &share->state.header,share->state_length,
  134.   MYF(MY_NABP)))
  135.       {
  136. error=my_errno;
  137. VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
  138. my_errno=error;
  139. break;
  140.       }
  141. #endif
  142.     }
  143.     VOID(_nisam_test_if_changed(info));
  144.     share->r_locks++;
  145.     info->lock_type=lock_type;
  146.     break;
  147.   case F_WRLCK:
  148.     if (info->lock_type == F_RDLCK)
  149.     { /* Change RW to READONLY */
  150.       if (share->r_locks == 1)
  151.       {
  152. flag=1;
  153. if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
  154.     MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
  155. {
  156.   error=my_errno;
  157.   break;
  158. }
  159. share->r_locks--;
  160. share->w_locks++;
  161. info->lock_type=lock_type;
  162. break;
  163.       }
  164.     }
  165.     if (!(share->base.options & HA_OPTION_READ_ONLY_DATA) && !share->w_locks)
  166.     {
  167.       flag=1;
  168.       VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
  169.       if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  170.       {
  171. error=my_errno;
  172. break;
  173.       }
  174.       if (!share->r_locks)
  175.       {
  176. if (my_read(share->kfile,
  177.     (char*) &share->state.header,share->state_length,
  178.     MYF(MY_NABP)))
  179. {
  180.   error=my_errno;
  181.   VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
  182.   my_errno=error;
  183.   break;
  184. }
  185.       }
  186.     }
  187.     VOID(_nisam_test_if_changed(info));
  188.     info->lock_type=lock_type;
  189.     share->w_locks++;
  190.     break;
  191.   default:
  192.     break; /* Impossible */
  193.   }
  194.   pthread_mutex_unlock(&share->intern_lock);
  195. #if defined(FULL_LOG) || defined(_lint)
  196.   lock_type|=(int) (flag << 8); /* Set bit to set if real lock */
  197.   nisam_log_command(LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type),
  198.     error);
  199. #endif
  200. #endif
  201.   DBUG_RETURN(error);
  202. } /* nisam_lock_database */
  203. /* Is used before access to database is granted */
  204. int _nisam_readinfo(register N_INFO *info, int lock_type, int check_keybuffer)
  205. {
  206.   ISAM_SHARE *share;
  207.   DBUG_ENTER("_nisam_readinfo");
  208.   share=info->s;
  209.   if (info->lock_type == F_UNLCK)
  210.   {
  211.     if (!share->r_locks && !share->w_locks)
  212.     {
  213. #ifndef HAVE_FCNTL
  214.       VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
  215. #endif
  216. #ifndef NO_LOCKING
  217. #ifdef UNSAFE_LOCKING
  218.       if ((info->tmp_lock_type=lock_type) != F_RDLCK)
  219. #endif
  220. if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
  221.   DBUG_RETURN(1);
  222. #endif
  223. #ifdef HAVE_FCNTL
  224.       if (my_pread(share->kfile,
  225.   (char*) &share->state.header,share->state_length,0L,
  226.   MYF(MY_NABP)))
  227. #else
  228.       if (my_read(share->kfile,
  229.   (char*) &share->state.header,share->state_length,
  230.   MYF(MY_NABP)))
  231. #endif
  232.       {
  233. #ifndef NO_LOCKING
  234. int error=my_errno;
  235. VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
  236.      MYF(MY_SEEK_NOT_DONE)));
  237. my_errno=error;
  238. #endif
  239. DBUG_RETURN(1);
  240.       }
  241.     }
  242.     if (check_keybuffer)
  243.       VOID(_nisam_test_if_changed(info));
  244.   }
  245.   else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
  246.   {
  247.     my_errno=EACCES; /* Not allowed to change */
  248.     DBUG_RETURN(-1); /* when have read_lock() */
  249.   }
  250.   DBUG_RETURN(0);
  251. } /* _nisam_readinfo */
  252. /* Every isam-function that uppdates the isam-database must! end */
  253. /* with this request */
  254. /* ARGSUSED */
  255. int _nisam_writeinfo(register N_INFO *info, uint flags)
  256. {
  257.   int error,olderror;
  258.   ISAM_SHARE *share;
  259.   DBUG_ENTER("_nisam_writeinfo");
  260.   error=0;
  261.   share=info->s;
  262.   if (share->r_locks == 0 && share->w_locks == 0)
  263.   {
  264.     olderror=my_errno; /* Remember last error */
  265.     if (flags)
  266.     { /* Two threads can't be here */
  267.       share->state.process= share->last_process=   share->this_process;
  268.       share->state.loop=    info->last_loop=     ++info->this_loop;
  269.       share->state.uniq=    info->last_uniq=    info->this_uniq;
  270.       if ((error=my_pwrite(share->kfile,(char*) &share->state.header,
  271.    share->state_length,0L,MYF(MY_NABP)) != 0))
  272. olderror=my_errno;
  273. #ifdef __WIN__
  274.       if (nisam_flush)
  275.       {
  276. _commit(share->kfile);
  277. _commit(info->dfile);
  278.       }
  279. #endif
  280.     }
  281.     if (flags != 2)
  282.     {
  283. #ifndef NO_LOCKING
  284. #ifdef UNSAFE_LOCKING
  285.       if (info->tmp_lock_type != F_RDLCK)
  286. #endif
  287.       {
  288. if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
  289.     MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
  290.   DBUG_RETURN(1);
  291.       }
  292. #endif
  293.     }
  294.     my_errno=olderror;
  295.   }
  296.   else if (flags)
  297.     share->changed= 1; /* Mark keyfile changed */
  298.   DBUG_RETURN(error);
  299. } /* _nisam_writeinfo */
  300. /* Test if someone has changed the database */
  301. /* (Should be called after readinfo) */
  302. int _nisam_test_if_changed(register N_INFO *info)
  303. {
  304. #ifndef NO_LOCKING
  305.   {
  306.     ISAM_SHARE *share=info->s;
  307.     if (share->state.process != share->last_process ||
  308. share->state.loop    != info->last_loop ||
  309. share->state.uniq    != info->last_uniq)
  310.     { /* Keyfile has changed */
  311.       if (share->state.process != share->this_process)
  312. VOID(flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE));
  313.       share->last_process=share->state.process;
  314.       info->last_loop= share->state.loop;
  315.       info->last_uniq= share->state.uniq;
  316.       info->update|= HA_STATE_WRITTEN; /* Must use file on next */
  317.       info->data_changed= 1; /* For nisam_is_changed */
  318.       return 1;
  319.     }
  320.   }
  321. #endif
  322.   return (!(info->update & HA_STATE_AKTIV) ||
  323.   (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
  324.    HA_STATE_KEY_CHANGED)));
  325. } /* _nisam_test_if_changed */