diff options
Diffstat (limited to 'bdb/os_win32/os_map.c')
-rw-r--r-- | bdb/os_win32/os_map.c | 118 |
1 files changed, 73 insertions, 45 deletions
diff --git a/bdb/os_win32/os_map.c b/bdb/os_win32/os_map.c index d7b2839ed29..1f16c9fead4 100644 --- a/bdb/os_win32/os_map.c +++ b/bdb/os_win32/os_map.c @@ -1,22 +1,21 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 1997, 1998, 1999, 2000 + * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "$Id: os_map.c,v 11.22 2000/10/26 14:18:08 bostic Exp $"; +static const char revid[] = "$Id: os_map.c,v 11.38 2002/09/10 02:35:48 bostic Exp $"; #endif /* not lint */ #include "db_int.h" -#include "os_jump.h" static int __os_map __P((DB_ENV *, char *, REGINFO *, DB_FH *, size_t, int, int, int, void **)); -static int __os_unique_name __P((char *, int, char *)); +static int __os_unique_name __P((char *, HANDLE, char *, size_t)); /* * __os_r_sysattach -- @@ -37,6 +36,7 @@ __os_r_sysattach(dbenv, infop, rp) * properly ordered, our caller has already taken care of that. */ if ((ret = __os_open(dbenv, infop->name, + DB_OSO_DIRECT | F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE: 0, infop->mode, &fh)) != 0) { __db_err(dbenv, "%s: %s", infop->name, db_strerror(ret)); @@ -63,7 +63,7 @@ __os_r_sysattach(dbenv, infop, rp) if (ret == 0 && is_system == 1) rp->segid = 1; - (void)__os_closehandle(&fh); + (void)__os_closehandle(dbenv, &fh); return (ret); } @@ -82,17 +82,19 @@ __os_r_sysdetach(dbenv, infop, destroy) if (infop->wnt_handle != NULL) { (void)CloseHandle(*((HANDLE*)(infop->wnt_handle))); - __os_free(infop->wnt_handle, sizeof(HANDLE)); + __os_free(dbenv, infop->wnt_handle); } - __os_set_errno(0); ret = !UnmapViewOfFile(infop->addr) ? __os_win32_errno() : 0; if (ret != 0) __db_err(dbenv, "UnmapViewOfFile: %s", strerror(ret)); - if (F_ISSET(dbenv, DB_ENV_SYSTEM_MEM) && destroy && - (t_ret = __os_unlink(dbenv, infop->name)) != 0 && ret == 0) - ret = t_ret; + if (!F_ISSET(dbenv, DB_ENV_SYSTEM_MEM) && destroy) { + if (F_ISSET(dbenv, DB_ENV_OVERWRITE)) + (void)__db_overwrite(dbenv, infop->name); + if ((t_ret = __os_unlink(dbenv, infop->name)) != 0 && ret == 0) + ret = t_ret; + } return (ret); } @@ -111,8 +113,8 @@ __os_mapfile(dbenv, path, fhp, len, is_rdonly, addr) void **addr; { /* If the user replaced the map call, call through their interface. */ - if (__db_jump.j_map != NULL) - return (__db_jump.j_map(path, len, 0, is_rdonly, addr)); + if (DB_GLOBAL(j_map) != NULL) + return (DB_GLOBAL(j_map)(path, len, 0, is_rdonly, addr)); return (__os_map(dbenv, path, NULL, fhp, len, 0, 0, is_rdonly, addr)); } @@ -128,10 +130,9 @@ __os_unmapfile(dbenv, addr, len) size_t len; { /* If the user replaced the map call, call through their interface. */ - if (__db_jump.j_unmap != NULL) - return (__db_jump.j_unmap(addr, len)); + if (DB_GLOBAL(j_unmap) != NULL) + return (DB_GLOBAL(j_unmap)(addr, len)); - __os_set_errno(0); return (!UnmapViewOfFile(addr) ? __os_win32_errno() : 0); } @@ -151,23 +152,55 @@ __os_unmapfile(dbenv, addr, len) * foo.bar == Foo.Bar (FAT file system) * foo.bar != Foo.Bar (NTFS) * - * The best solution is to use the identifying number in the file + * The best solution is to use the file index, found in the file * information structure (similar to UNIX inode #). + * + * When a file is deleted, its file index may be reused, + * but if the unique name has not gone from its namespace, + * we may get a conflict. So to ensure some tie in to the + * original pathname, we also use the creation time and the + * file basename. This is not a perfect system, but it + * should work for all but anamolous test cases. + * */ static int -__os_unique_name(orig_path, fd, result_path) +__os_unique_name(orig_path, hfile, result_path, result_path_len) char *orig_path, *result_path; - int fd; + HANDLE hfile; + size_t result_path_len; { BY_HANDLE_FILE_INFORMATION fileinfo; + char *basename, *p; - __os_set_errno(0); - if (!GetFileInformationByHandle( - (HANDLE)_get_osfhandle(fd), &fileinfo)) + /* + * In Windows, pathname components are delimited by '/' or '\', and + * if neither is present, we need to strip off leading drive letter + * (e.g. c:foo.txt). + */ + basename = strrchr(orig_path, '/'); + p = strrchr(orig_path, '\\'); + if (basename == NULL || (p != NULL && p > basename)) + basename = p; + if (basename == NULL) + basename = strrchr(orig_path, ':'); + + if (basename == NULL) + basename = orig_path; + else + basename++; + + if (!GetFileInformationByHandle(hfile, &fileinfo)) return (__os_win32_errno()); - (void)sprintf(result_path, "%ld.%ld.%ld", + + (void)snprintf(result_path, result_path_len, + "__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s", fileinfo.dwVolumeSerialNumber, - fileinfo.nFileIndexHigh, fileinfo.nFileIndexLow); + fileinfo.nFileIndexHigh, + fileinfo.nFileIndexLow, + fileinfo.ftCreationTime.dwHighDateTime, + fileinfo.ftCreationTime.dwHighDateTime, + basename); + return (0); } @@ -187,10 +220,9 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) { HANDLE hMemory; REGENV *renv; - int ret; - void *pMemory; + int ret, use_pagefile; char shmem_name[MAXPATHLEN]; - int use_pagefile; + void *pMemory; ret = 0; if (infop != NULL) @@ -202,12 +234,9 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) * If creating a region in system space, get a matching name in the * paging file namespace. */ - if (use_pagefile) { - (void)strcpy(shmem_name, "__db_shmem."); - if ((ret = __os_unique_name(path, fhp->fd, - &shmem_name[strlen(shmem_name)])) != 0) - return (ret); - } + if (use_pagefile && (ret = __os_unique_name( + path, fhp->handle, shmem_name, sizeof(shmem_name))) != 0) + return (ret); /* * XXX @@ -235,7 +264,6 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) * the section. */ hMemory = NULL; - __os_set_errno(0); if (use_pagefile) hMemory = OpenFileMapping( is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, @@ -244,24 +272,23 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) if (hMemory == NULL) hMemory = CreateFileMapping( - use_pagefile ? - (HANDLE)0xFFFFFFFF : (HANDLE)_get_osfhandle(fhp->fd), + use_pagefile ? (HANDLE)-1 : fhp->handle, 0, is_rdonly ? PAGE_READONLY : PAGE_READWRITE, - 0, len, + 0, (DWORD)len, use_pagefile ? shmem_name : NULL); if (hMemory == NULL) { - __db_err(dbenv, - "OpenFileMapping: %s", strerror(__os_win32_errno())); - return (__os_win32_errno()); + ret = __os_win32_errno(); + __db_err(dbenv, "OpenFileMapping: %s", strerror(ret)); + return (ret); } pMemory = MapViewOfFile(hMemory, (is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 0, 0, len); if (pMemory == NULL) { - __db_err(dbenv, - "MapViewOfFile: %s", strerror(__os_win32_errno())); - return (__os_win32_errno()); + ret = __os_win32_errno(); + __db_err(dbenv, "MapViewOfFile: %s", strerror(ret)); + return (ret); } /* @@ -279,8 +306,8 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) * errors, it just means we leak the memory. */ if (use_pagefile && infop != NULL) { - if (__os_malloc(NULL, - sizeof(HANDLE), NULL, &infop->wnt_handle) == 0) + if (__os_malloc(dbenv, + sizeof(HANDLE), &infop->wnt_handle) == 0) memcpy(infop->wnt_handle, &hMemory, sizeof(HANDLE)); } else CloseHandle(hMemory); @@ -295,7 +322,7 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) * the REGINFO structure so that they do so. */ renv = (REGENV *)pMemory; - if (renv->magic == 0) + if (renv->magic == 0) { if (F_ISSET(infop, REGION_CREATE_OK)) F_SET(infop, REGION_CREATE); else { @@ -303,6 +330,7 @@ __os_map(dbenv, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) pMemory = NULL; ret = EAGAIN; } + } } *addr = pMemory; |