diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Eprivate.h | 30 | ||||
-rw-r--r-- | src/H5Fint.c | 36 | ||||
-rw-r--r-- | src/H5system.c | 100 | ||||
-rw-r--r-- | src/H5win32defs.h | 1 |
4 files changed, 106 insertions, 61 deletions
diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h index 58010a3..c3c440f 100644 --- a/src/H5Eprivate.h +++ b/src/H5Eprivate.h @@ -111,6 +111,7 @@ typedef struct H5E_t H5E_t; /* Retrieve the error code description string and push it onto the error * stack. */ +#ifndef H5_HAVE_WIN32_API #define HSYS_DONE_ERROR(majorcode, minorcode, retcode, str) \ { \ int myerrno = errno; \ @@ -129,6 +130,35 @@ typedef struct H5E_t H5E_t; HGOTO_ERROR(majorcode, minorcode, retcode, "%s, errno = %d, error message = '%s'", str, myerrno, \ HDstrerror(myerrno)); \ } +#else /* H5_HAVE_WIN32_API */ +/* On Windows we also emit the result of GetLastError(). This call returns a DWORD, which is always a + * 32-bit unsigned type. Note that on Windows, either errno or GetLastError() (but probably not both) will + * be useful depending on whether a C/POSIX or Win32 call failed. The other value will likely be zero, + * though I wouldn't count on that. + */ +#define HSYS_DONE_ERROR(majorcode, minorcode, retcode, str) \ + { \ + int myerrno = errno; \ + DWORD win_error = GetLastError(); \ + /* Other projects may rely on the description format to get the errno and any changes should be \ + * considered as an API change \ + */ \ + HDONE_ERROR(majorcode, minorcode, retcode, \ + "%s, errno = %d, error message = '%s', Win32 GetLastError() = %" PRIu32 "", str, \ + myerrno, HDstrerror(myerrno), win_error); \ + } +#define HSYS_GOTO_ERROR(majorcode, minorcode, retcode, str) \ + { \ + int myerrno = errno; \ + DWORD win_error = GetLastError(); \ + /* Other projects may rely on the description format to get the errno and any changes should be \ + * considered as an API change \ + */ \ + HGOTO_ERROR(majorcode, minorcode, retcode, \ + "%s, errno = %d, error message = '%s', Win32 GetLastError() = %" PRIu32 "", str, \ + myerrno, HDstrerror(myerrno), win_error); \ + } +#endif /* H5_HAVE_WIN32_API */ #ifdef H5_HAVE_PARALLEL /* diff --git a/src/H5Fint.c b/src/H5Fint.c index 9ddd3d7..c8e2cad 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -918,9 +918,10 @@ done: htri_t H5F__is_hdf5(const char *name) { - H5FD_t *file = NULL; /* Low-level file struct */ - haddr_t sig_addr = HADDR_UNDEF; /* Addess of hdf5 file signature */ - htri_t ret_value = FAIL; /* Return value */ + H5FD_t * file = NULL; /* Low-level file struct */ + H5F_shared_t *shared = NULL; /* Shared part of file */ + haddr_t sig_addr = HADDR_UNDEF; /* Addess of hdf5 file signature */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_PACKAGE @@ -928,10 +929,20 @@ H5F__is_hdf5(const char *name) if (NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to open file") - /* The file is an hdf5 file if the hdf5 file signature can be found */ - if (H5FD_locate_signature(file, &sig_addr) < 0) - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "error while trying to locate file signature") - ret_value = (HADDR_UNDEF != sig_addr); + /* If the file is already open, it's an HDF5 file + * + * If the file is open with an exclusive lock on an operating system that enforces + * mandatory file locks (like Windows), creating a new file handle and attempting + * to read through it will fail so we have to try this first. + */ + if ((shared = H5F__sfile_search(file)) != NULL) + ret_value = TRUE; + else { + /* The file is an HDF5 file if the HDF5 file signature can be found */ + if (H5FD_locate_signature(file, &sig_addr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "error while trying to locate file signature") + ret_value = (HADDR_UNDEF != sig_addr); + } done: /* Close the file */ @@ -1603,7 +1614,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) FUNC_ENTER_NOAPI(NULL) /* - * If the driver has a `cmp' method then the driver is capable of + * If the driver has a 'cmp' method then the driver is capable of * determining when two file handles refer to the same file and the * library can insure that when the application opens a file twice * that the two handles coordinate their operations appropriately. @@ -3546,10 +3557,17 @@ H5F__start_swmr_write(H5F_t *f) setup = TRUE; /* Place an advisory lock on the file */ - if (H5F_USE_FILE_LOCKING(f)) + if (H5F_USE_FILE_LOCKING(f)) { + /* Have to unlock on Windows as Win32 doesn't support changing the lock + * type (exclusive vs shared) with a second call. + */ + if (H5FD_unlock(f->shared->lf) < 0) { + HGOTO_ERROR(H5E_FILE, H5E_CANTUNLOCKFILE, FAIL, "unable to unlock the file") + } if (H5FD_lock(f->shared->lf, TRUE) < 0) { HGOTO_ERROR(H5E_FILE, H5E_CANTLOCKFILE, FAIL, "unable to lock the file") } + } /* Mark superblock as dirty */ if (H5F_super_dirty(f) < 0) diff --git a/src/H5system.c b/src/H5system.c index 26054e7..99a6f4d 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -924,8 +924,8 @@ Wgetlogin(void) { #ifdef H5_HAVE_WINSOCK2_H - long bufferCount = WloginBuffer_count; - if (GetUserName(Wlogin_buffer, &bufferCount) == 0) + DWORD bufferCount = WloginBuffer_count; + if (GetUserName(Wlogin_buffer, &bufferCount) != 0) return (Wlogin_buffer); else #endif /* H5_HAVE_WINSOCK2_H */ @@ -969,61 +969,45 @@ c99_vsnprintf(char *str, size_t size, const char *format, va_list ap) *------------------------------------------------------------------------- */ int -Wflock(int H5_ATTR_UNUSED fd, int H5_ATTR_UNUSED operation) +Wflock(int fd, int operation) { -/* This is a no-op while we implement a Win32 VFD */ -#if 0 -int -Wflock(int fd, int operation) { - - HANDLE hFile; - DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; - DWORD dwReserved = 0; - /* MAXDWORD for entire file */ - DWORD nNumberOfBytesToLockLow = MAXDWORD; - DWORD nNumberOfBytesToLockHigh = MAXDWORD; - /* Must initialize OVERLAPPED struct */ - OVERLAPPED overlapped = {0}; + HANDLE hFile; + DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; + DWORD dwReserved = 0; + /* MAXDWORD locks the entire file */ + DWORD nNumberOfBytesToLockLow = MAXDWORD; + DWORD nNumberOfBytesToLockHigh = MAXDWORD; + /* Must initialize OVERLAPPED struct */ + OVERLAPPED overlapped = {0}; /* Get Windows HANDLE */ - hFile = _get_osfhandle(fd); + if (INVALID_HANDLE_VALUE == (hFile = (HANDLE)_get_osfhandle(fd))) + return -1; /* Convert to Windows flags */ - if(operation & LOCK_EX) + if (operation & LOCK_EX) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; /* Lock or unlock */ - if(operation & LOCK_UN) - if(0 == UnlockFileEx(hFile, dwReserved, nNumberOfBytesToLockLow, - nNumberOfBytesToLockHigh, &overlapped)) - return -1; - else - if(0 == LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, - nNumberOfBytesToLockHigh, &overlapped)) + if (operation & LOCK_UN) { + if (0 == + UnlockFileEx(hFile, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, &overlapped)) { + /* Attempting to unlock an already unlocked file will fail and this can happen + * in H5Fstart_swmr_write(). For now, just ignore the "error" (error code: 0x9e / 158). + */ + if (GetLastError() != 158) + return -1; + } + } + else { + if (0 == LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, + &overlapped)) return -1; -#endif /* 0 */ - return 0; -} /* end Wflock() */ + } -/*-------------------------------------------------------------------------- - * Function: Wnanosleep - * - * Purpose: Sleep for a given # of nanoseconds (Windows version) - * - * Return: SUCCEED/FAIL - * - * Programmer: Dana Robinson - * Fall 2016 - *-------------------------------------------------------------------------- - */ -int -Wnanosleep(const struct timespec *req, struct timespec *rem) -{ - /* XXX: Currently just a placeholder */ return 0; - -} /* end Wnanosleep() */ +} /* end Wflock() */ /*------------------------------------------------------------------------- * Function: Wllround, Wllroundf, Wlround, Wlroundf, Wround, Wroundf @@ -1403,6 +1387,9 @@ done: * * Purpose: Sleep for a given # of nanoseconds * + * Note that commodity hardware is probably going to have a + * resolution of milliseconds, not nanoseconds. + * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol @@ -1412,15 +1399,26 @@ done: void H5_nanosleep(uint64_t nanosec) { - struct timespec sleeptime; /* Struct to hold time to sleep */ - FUNC_ENTER_NOAPI_NOINIT_NOERR - /* Set up time to sleep */ - sleeptime.tv_sec = 0; - sleeptime.tv_nsec = (long)nanosec; +#ifdef H5_HAVE_WIN32_API + + /* On Windows, Sleep() is in milliseconds. Passing 0 to Sleep() + * causes the thread to relinquish the rest of its time slice. + */ + Sleep(nanosec / (1000 * 1000)); + +#else + { + struct timespec sleeptime; /* Struct to hold time to sleep */ + + /* Set up time to sleep */ + sleeptime.tv_sec = 0; + sleeptime.tv_nsec = (long)nanosec; - HDnanosleep(&sleeptime, NULL); + HDnanosleep(&sleeptime, NULL); + } +#endif FUNC_LEAVE_NOAPI_VOID } /* end H5_nanosleep() */ diff --git a/src/H5win32defs.h b/src/H5win32defs.h index 8f3947a..9cd0afb 100644 --- a/src/H5win32defs.h +++ b/src/H5win32defs.h @@ -174,7 +174,6 @@ H5_DLL int Wflock(int fd, int operation); H5_DLL char * Wgetlogin(void); H5_DLL int c99_snprintf(char *str, size_t size, const char *format, ...); H5_DLL int c99_vsnprintf(char *str, size_t size, const char *format, va_list ap); -H5_DLL int Wnanosleep(const struct timespec *req, struct timespec *rem); H5_DLL herr_t H5_expand_windows_env_vars(char **env_var); H5_DLL wchar_t *H5_get_utf16_str(const char *s); H5_DLL int Wopen_utf8(const char *path, int oflag, ...); |