_locking.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

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