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

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: os_open.c,v 11.9 2000/11/30 00:58:43 ubell Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <fcntl.h>
  14. #include <signal.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #endif
  18. #include "db_int.h"
  19. #include "os_jump.h"
  20. int __os_win32_errno __P((void));
  21. /*
  22.  * __os_open --
  23.  * Open a file descriptor.
  24.  */
  25. int
  26. __os_open(dbenv, name, flags, mode, fhp)
  27. DB_ENV *dbenv;
  28. const char *name;
  29. u_int32_t flags;
  30. int mode;
  31. DB_FH *fhp;
  32. {
  33. DWORD bytesWritten;
  34. HANDLE wh;
  35. u_int32_t log_size;
  36. int access, attr, oflags, share, createflag;
  37. int ret, nrepeat;
  38. /*
  39.  * The "public" interface to the __os_open routine passes around POSIX
  40.  * 1003.1 flags, not DB flags.  If the user has defined their own open
  41.  * interface, use the POSIX flags.
  42.  */
  43. if (__db_jump.j_open != NULL) {
  44. oflags = O_BINARY | O_NOINHERIT;
  45. if (LF_ISSET(DB_OSO_CREATE))
  46. oflags |= O_CREAT;
  47. if (LF_ISSET(DB_OSO_EXCL))
  48. oflags |= O_EXCL;
  49. if (LF_ISSET(DB_OSO_RDONLY))
  50. oflags |= O_RDONLY;
  51. else
  52. oflags |= O_RDWR;
  53. if (LF_ISSET(DB_OSO_SEQ))
  54. oflags |= _O_SEQUENTIAL;
  55. else
  56. oflags |= _O_RANDOM;
  57. if (LF_ISSET(DB_OSO_TEMP))
  58. oflags |= _O_TEMPORARY;
  59. if (LF_ISSET(DB_OSO_TRUNC))
  60. oflags |= O_TRUNC;
  61. return (__os_openhandle(dbenv, name, oflags, mode, fhp));
  62. }
  63. if (LF_ISSET(DB_OSO_LOG))
  64. log_size = fhp->log_size; /* XXX: Gag. */
  65. memset(fhp, 0, sizeof(*fhp));
  66. /*
  67.  * Otherwise, use the Windows/32 CreateFile interface so that we can
  68.  * play magic games with log files to get data flush effects similar
  69.  * to the POSIX O_DSYNC flag.
  70.  *
  71.  * !!!
  72.  * We currently ignore the 'mode' argument.  It would be possible
  73.  * to construct a set of security attributes that we could pass to
  74.  * CreateFile that would accurately represents the mode.  In worst
  75.  * case, this would require looking up user and all group names and
  76.  * creating an entry for each.  Alternatively, we could call the
  77.  * _chmod (partial emulation) function after file creation, although
  78.  * this leaves us with an obvious race.  However, these efforts are
  79.  * largely meaningless on FAT, the most common file system, which
  80.  * only has a "readable" and "writeable" flag, applying to all users.
  81.  */
  82. wh = INVALID_HANDLE_VALUE;
  83. access = GENERIC_READ;
  84. if (!LF_ISSET(DB_OSO_RDONLY))
  85. access |= GENERIC_WRITE;
  86. share = FILE_SHARE_READ | FILE_SHARE_WRITE;
  87. attr = FILE_ATTRIBUTE_NORMAL;
  88. /*
  89.  * Reproduce POSIX 1003.1 semantics: if O_CREATE and O_EXCL are both
  90.  * specified, fail, returning EEXIST, unless we create the file.
  91.  */
  92. if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_EXCL))
  93. createflag = CREATE_NEW; /* create only if !exist*/
  94. else if (!LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_TRUNC))
  95. createflag = TRUNCATE_EXISTING; /* truncate, fail if !exist */
  96. else if (LF_ISSET(DB_OSO_TRUNC))
  97. createflag = CREATE_ALWAYS; /* create and truncate */
  98. else if (LF_ISSET(DB_OSO_CREATE))
  99. createflag = OPEN_ALWAYS; /* open or create */
  100. else
  101. createflag = OPEN_EXISTING; /* open only if existing */
  102. if (LF_ISSET(DB_OSO_LOG)) {
  103. F_SET(fhp, DB_FH_NOSYNC);
  104. attr |= FILE_FLAG_WRITE_THROUGH;
  105. }
  106. if (LF_ISSET(DB_OSO_SEQ))
  107. attr |= FILE_FLAG_SEQUENTIAL_SCAN;
  108. else
  109. attr |= FILE_FLAG_RANDOM_ACCESS;
  110. if (LF_ISSET(DB_OSO_TEMP))
  111. attr |= FILE_FLAG_DELETE_ON_CLOSE;
  112. for (nrepeat = 1; nrepeat < 4; ++nrepeat) {
  113. ret = 0;
  114. __os_set_errno(0);
  115. wh = CreateFile(name, access, share, NULL, createflag, attr, 0);
  116. if (wh == INVALID_HANDLE_VALUE) {
  117. /*
  118.  * If it's a "temporary" error, we retry up to 3 times,
  119.  * waiting up to 12 seconds.  While it's not a problem
  120.  * if we can't open a database, an inability to open a
  121.  * log file is cause for serious dismay.
  122.  */
  123. ret = __os_win32_errno();
  124. if (ret == ENFILE || ret == EMFILE || ret == ENOSPC) {
  125. (void)__os_sleep(dbenv, nrepeat * 2, 0);
  126. continue;
  127. }
  128. goto err;
  129. }
  130. break;
  131. }
  132. /*
  133.  * Special handling needed for log files.  To get Windows to not update
  134.  * the MFT metadata on each write, extend the file to its maximum size.
  135.  * Windows will allocate all the data blocks and store them in the MFT
  136.  * (inode) area.  In addition, flush the MFT area to disk.
  137.  * This strategy only works for Win/NT; Win/9X does not
  138.  * guarantee that the logs will be zero filled.
  139.  */
  140. if (LF_ISSET(DB_OSO_LOG) && log_size != 0 &&
  141.     __os_is_winnt()) {
  142. if (SetFilePointer(wh,
  143.     log_size - 1, NULL, FILE_BEGIN) == (DWORD)-1)
  144. goto err;
  145. if (WriteFile(wh, "x00", 1, &bytesWritten, NULL) == 0)
  146. goto err;
  147. if (bytesWritten != 1)
  148. goto err;
  149. if (SetEndOfFile(wh) == 0)
  150. goto err;
  151. if (SetFilePointer(wh, 0, NULL, FILE_BEGIN) == (DWORD)-1)
  152. goto err;
  153. if (FlushFileBuffers(wh) == 0)
  154. goto err;
  155. }
  156. /*
  157.  * We acquire a POSIX file descriptor as this allows us to use the
  158.  * general UNIX I/O routines instead of writing Windows specific
  159.  * ones.  Closing that file descriptor is sufficient to close the
  160.  * Windows HANDLE.
  161.  */
  162. fhp->fd =
  163.     _open_osfhandle((long)wh, LF_ISSET(DB_OSO_RDONLY) ? O_RDONLY : 0);
  164. fhp->handle = wh;
  165. F_SET(fhp, DB_FH_VALID);
  166. return (0);
  167. err: if (ret == 0)
  168. ret = __os_win32_errno();
  169. if (wh != INVALID_HANDLE_VALUE)
  170. (void)CloseHandle(wh);
  171. return (ret);
  172. }