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

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: os_map.c,v 11.38 2002/09/10 02:35:48 bostic Exp $";
  10. #endif /* not lint */
  11. #include "db_int.h"
  12. static int __os_map
  13.   __P((DB_ENV *, char *, REGINFO *, DB_FH *, size_t, int, int, int, void **));
  14. static int __os_unique_name __P((char *, HANDLE, char *, size_t));
  15. /*
  16.  * __os_r_sysattach --
  17.  * Create/join a shared memory region.
  18.  */
  19. int
  20. __os_r_sysattach(dbenv, infop, rp)
  21. DB_ENV *dbenv;
  22. REGINFO *infop;
  23. REGION *rp;
  24. {
  25. DB_FH fh;
  26. int is_system, ret;
  27. /*
  28.  * Try to open/create the file.  We DO NOT need to ensure that multiple
  29.  * threads/processes attempting to simultaneously create the region are
  30.  * properly ordered, our caller has already taken care of that.
  31.  */
  32. if ((ret = __os_open(dbenv, infop->name,
  33.     DB_OSO_DIRECT |
  34.     F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE: 0,
  35.     infop->mode, &fh)) != 0) {
  36. __db_err(dbenv, "%s: %s", infop->name, db_strerror(ret));
  37. return (ret);
  38. }
  39. /*
  40.  * On Windows/9X, files that are opened by multiple processes do not
  41.  * share data correctly.  For this reason, the DB_SYSTEM_MEM flag is
  42.  * implied for any application that does not specify the DB_PRIVATE
  43.  * flag.
  44.  */
  45. is_system = F_ISSET(dbenv, DB_ENV_SYSTEM_MEM) ||
  46.     (!F_ISSET(dbenv, DB_ENV_PRIVATE) && __os_is_winnt() == 0);
  47. /*
  48.  * Map the file in.  If we're creating an in-system-memory region,
  49.  * specify a segment ID (which is never used again) so that the
  50.  * calling code writes out the REGENV_REF structure to the primary
  51.  * environment file.
  52.  */
  53. ret = __os_map(dbenv, infop->name, infop, &fh, rp->size,
  54.    1, is_system, 0, &infop->addr);
  55. if (ret == 0 && is_system == 1)
  56. rp->segid = 1;
  57. (void)__os_closehandle(dbenv, &fh);
  58. return (ret);
  59. }
  60. /*
  61.  * __os_r_sysdetach --
  62.  * Detach from a shared memory region.
  63.  */
  64. int
  65. __os_r_sysdetach(dbenv, infop, destroy)
  66. DB_ENV *dbenv;
  67. REGINFO *infop;
  68. int destroy;
  69. {
  70. int ret, t_ret;
  71. if (infop->wnt_handle != NULL) {
  72. (void)CloseHandle(*((HANDLE*)(infop->wnt_handle)));
  73. __os_free(dbenv, infop->wnt_handle);
  74. }
  75. ret = !UnmapViewOfFile(infop->addr) ? __os_win32_errno() : 0;
  76. if (ret != 0)
  77. __db_err(dbenv, "UnmapViewOfFile: %s", strerror(ret));
  78. if (!F_ISSET(dbenv, DB_ENV_SYSTEM_MEM) && destroy) {
  79. if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
  80. (void)__db_overwrite(dbenv, infop->name);
  81. if ((t_ret = __os_unlink(dbenv, infop->name)) != 0 && ret == 0)
  82. ret = t_ret;
  83. }
  84. return (ret);
  85. }
  86. /*
  87.  * __os_mapfile --
  88.  * Map in a shared memory file.
  89.  */
  90. int
  91. __os_mapfile(dbenv, path, fhp, len, is_rdonly, addr)
  92. DB_ENV *dbenv;
  93. char *path;
  94. DB_FH *fhp;
  95. int is_rdonly;
  96. size_t len;
  97. void **addr;
  98. {
  99. /* If the user replaced the map call, call through their interface. */
  100. if (DB_GLOBAL(j_map) != NULL)
  101. return (DB_GLOBAL(j_map)(path, len, 0, is_rdonly, addr));
  102. return (__os_map(dbenv, path, NULL, fhp, len, 0, 0, is_rdonly, addr));
  103. }
  104. /*
  105.  * __os_unmapfile --
  106.  * Unmap the shared memory file.
  107.  */
  108. int
  109. __os_unmapfile(dbenv, addr, len)
  110. DB_ENV *dbenv;
  111. void *addr;
  112. size_t len;
  113. {
  114. /* If the user replaced the map call, call through their interface. */
  115. if (DB_GLOBAL(j_unmap) != NULL)
  116. return (DB_GLOBAL(j_unmap)(addr, len));
  117. return (!UnmapViewOfFile(addr) ? __os_win32_errno() : 0);
  118. }
  119. /*
  120.  * __os_unique_name --
  121.  * Create a unique identifying name from a pathname (may be absolute or
  122.  * relative) and/or a file descriptor.
  123.  *
  124.  * The name returned must be unique (different files map to different
  125.  * names), and repeatable (same files, map to same names).  It's not
  126.  * so easy to do by name.  Should handle not only:
  127.  *
  128.  * foo.bar  ==  ./foo.bar  ==  c:/whatever_path/foo.bar
  129.  *
  130.  * but also understand that:
  131.  *
  132.  * foo.bar  ==  Foo.Bar (FAT file system)
  133.  * foo.bar  !=  Foo.Bar (NTFS)
  134.  *
  135.  * The best solution is to use the file index, found in the file
  136.  * information structure (similar to UNIX inode #).
  137.  *
  138.  * When a file is deleted, its file index may be reused,
  139.  * but if the unique name has not gone from its namespace,
  140.  * we may get a conflict.  So to ensure some tie in to the
  141.  * original pathname, we also use the creation time and the
  142.  * file basename.  This is not a perfect system, but it
  143.  * should work for all but anamolous test cases.
  144.  *
  145.  */
  146. static int
  147. __os_unique_name(orig_path, hfile, result_path, result_path_len)
  148. char *orig_path, *result_path;
  149. HANDLE hfile;
  150. size_t result_path_len;
  151. {
  152. BY_HANDLE_FILE_INFORMATION fileinfo;
  153. char *basename, *p;
  154. /*
  155.  * In Windows, pathname components are delimited by '/' or '', and
  156.  * if neither is present, we need to strip off leading drive letter
  157.  * (e.g. c:foo.txt).
  158.  */
  159. basename = strrchr(orig_path, '/');
  160. p = strrchr(orig_path, '\');
  161. if (basename == NULL || (p != NULL && p > basename))
  162. basename = p;
  163. if (basename == NULL)
  164. basename = strrchr(orig_path, ':');
  165. if (basename == NULL)
  166. basename = orig_path;
  167. else
  168. basename++;
  169. if (!GetFileInformationByHandle(hfile, &fileinfo))
  170. return (__os_win32_errno());
  171. (void)snprintf(result_path, result_path_len,
  172.     "__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s",
  173.     fileinfo.dwVolumeSerialNumber,
  174.     fileinfo.nFileIndexHigh,
  175.     fileinfo.nFileIndexLow,
  176.     fileinfo.ftCreationTime.dwHighDateTime,
  177.     fileinfo.ftCreationTime.dwHighDateTime,
  178.     basename);
  179. return (0);
  180. }
  181. /*
  182.  * __os_map --
  183.  * The mmap(2) function for Windows.
  184.  */
  185. static int
  186. __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr)
  187. DB_ENV *dbenv;
  188. REGINFO *infop;
  189. char *path;
  190. DB_FH *fhp;
  191. int is_region, is_system, is_rdonly;
  192. size_t len;
  193. void **addr;
  194. {
  195. HANDLE hMemory;
  196. REGENV *renv;
  197. int ret, use_pagefile;
  198. char shmem_name[MAXPATHLEN];
  199. void *pMemory;
  200. ret = 0;
  201. if (infop != NULL)
  202. infop->wnt_handle = NULL;
  203. use_pagefile = is_region && is_system;
  204. /*
  205.  * If creating a region in system space, get a matching name in the
  206.  * paging file namespace.
  207.  */
  208. if (use_pagefile && (ret = __os_unique_name(
  209.     path, fhp->handle, shmem_name, sizeof(shmem_name))) != 0)
  210. return (ret);
  211. /*
  212.  * XXX
  213.  * DB: We have not implemented copy-on-write here.
  214.  *
  215.  * XXX
  216.  * DB: This code will fail if the library is ever compiled on a 64-bit
  217.  * machine.
  218.  *
  219.  * XXX
  220.  * If this is an region in system memory, let's try opening using the
  221.  * OpenFileMapping() first.  Why, oh why are we doing this?
  222.  *
  223.  * Well, we might be asking the OS for a handle to a pre-existing
  224.  * memory section, or we might be the first to get here and want the
  225.  * section created. CreateFileMapping() sounds like it will do both
  226.  * jobs. But, not so. It seems to mess up making the commit charge to
  227.  * the process. It thinks, incorrectly, that when we want to join a
  228.  * previously existing section, that it should make a commit charge
  229.  * for the whole section.  In fact, there is no new committed memory
  230.  * whatever.  The call can fail if there is insufficient memory free
  231.  * to handle the erroneous commit charge.  So, we find that the bogus
  232.  * commit is not made if we call OpenFileMapping().  So we do that
  233.  * first, and only call CreateFileMapping() if we're really creating
  234.  * the section.
  235.  */
  236. hMemory = NULL;
  237. if (use_pagefile)
  238. hMemory = OpenFileMapping(
  239.     is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
  240.     0,
  241.     shmem_name);
  242. if (hMemory == NULL)
  243. hMemory = CreateFileMapping(
  244.     use_pagefile ? (HANDLE)-1 : fhp->handle,
  245.     0,
  246.     is_rdonly ? PAGE_READONLY : PAGE_READWRITE,
  247.     0, (DWORD)len,
  248.     use_pagefile ? shmem_name : NULL);
  249. if (hMemory == NULL) {
  250. ret = __os_win32_errno();
  251. __db_err(dbenv, "OpenFileMapping: %s", strerror(ret));
  252. return (ret);
  253. }
  254. pMemory = MapViewOfFile(hMemory,
  255.     (is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 0, 0, len);
  256. if (pMemory == NULL) {
  257. ret = __os_win32_errno();
  258. __db_err(dbenv, "MapViewOfFile: %s", strerror(ret));
  259. return (ret);
  260. }
  261. /*
  262.  * XXX
  263.  * It turns out that the kernel object underlying the named section
  264.  * is reference counted, but that the call to MapViewOfFile() above
  265.  * does NOT increment the reference count! So, if we close the handle
  266.  * here, the kernel deletes the object from the kernel namespace.
  267.  * When a second process comes along to join the region, the kernel
  268.  * happily creates a new object with the same name, but completely
  269.  * different identity. The two processes then have distinct isolated
  270.  * mapped sections, not at all what was wanted. Not closing the handle
  271.  * here fixes this problem.  We carry the handle around in the region
  272.  * structure so we can close it when unmap is called.  Ignore malloc
  273.  * errors, it just means we leak the memory.
  274.  */
  275. if (use_pagefile && infop != NULL) {
  276. if (__os_malloc(dbenv,
  277.     sizeof(HANDLE), &infop->wnt_handle) == 0)
  278. memcpy(infop->wnt_handle, &hMemory, sizeof(HANDLE));
  279. } else
  280. CloseHandle(hMemory);
  281. if (is_region) {
  282. /*
  283.  * XXX
  284.  * Windows/95 zeroes anonymous memory regions at last close.
  285.  * This means that the backing file can exist and reference
  286.  * the region, but the region itself is no longer initialized.
  287.  * If the caller is capable of creating the region, update
  288.  * the REGINFO structure so that they do so.
  289.  */
  290. renv = (REGENV *)pMemory;
  291. if (renv->magic == 0) {
  292. if (F_ISSET(infop, REGION_CREATE_OK))
  293. F_SET(infop, REGION_CREATE);
  294. else {
  295. (void)UnmapViewOfFile(pMemory);
  296. pMemory = NULL;
  297. ret = EAGAIN;
  298. }
  299. }
  300. }
  301. *addr = pMemory;
  302. return (ret);
  303. }