Beispiel #1
0
/*
 * __wt_to_utf8_string --
 *  Convert UTF-16 encoded string to UTF-8.
 */
int
__wt_to_utf8_string(
    WT_SESSION_IMPL *session, const wchar_t* wide, WT_ITEM **outbuf)
{
	DWORD windows_error;
	int bufferSize;
	WT_DECL_RET;

	bufferSize = WideCharToMultiByte(
	    CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL);
	windows_error = __wt_getlasterror();

	if (bufferSize == 0 && windows_error != ERROR_INSUFFICIENT_BUFFER) {
		__wt_errx(session, "WideCharToMultiByte: %s",
		    __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}

	WT_RET(__wt_scr_alloc(session, bufferSize, outbuf));

	bufferSize = WideCharToMultiByte(
	    CP_UTF8, 0, wide, -1, (*outbuf)->mem, bufferSize, NULL, NULL);
	if (bufferSize == 0) {
		windows_error = __wt_getlasterror();
		__wt_scr_free(session, outbuf);
		__wt_errx(session, "WideCharToMultiByte: %s",
		    __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}

	(*outbuf)->size = bufferSize;
	return (0);
}
Beispiel #2
0
/*
 * __win_fs_rename --
 *	Rename a file.
 */
static int
__win_fs_rename(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags)
{
	DWORD windows_error;
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);
	WT_UNUSED(flags);

	session = (WT_SESSION_IMPL *)wt_session;

	/*
	 * Check if file exists since Windows does not override the file if
	 * it exists.
	 */
	if (GetFileAttributesA(to) != INVALID_FILE_ATTRIBUTES)
		if (DeleteFileA(to) == FALSE) {
			windows_error = __wt_getlasterror();
			__wt_errx(session,
			    "%s: file-rename: DeleteFileA: %s",
			    to, __wt_formatmessage(session, windows_error));
			return (__wt_map_windows_error(windows_error));
		}

	if (MoveFileA(from, to) == FALSE) {
		windows_error = __wt_getlasterror();
		__wt_errx(session,
		    "%s to %s: file-rename: MoveFileA: %s",
		    from, to, __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}

	return (0);
}
Beispiel #3
0
/*
 * __win_file_sync --
 *	MSVC fsync.
 */
static int
__win_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
{
	DWORD windows_error;
	WT_DECL_RET;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	/*
	 * We don't open Windows system handles when opening directories
	 * for flushing, as it is not necessary (or possible) to flush
	 * a directory on Windows. Confirm the file handle is set before
	 * attempting to sync it.
	 */
	if (win_fh->filehandle == INVALID_HANDLE_VALUE)
		return (0);

	if (FlushFileBuffers(win_fh->filehandle) == FALSE) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s handle-sync: FlushFileBuffers: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
		return (ret);
	}
	return (0);
}
Beispiel #4
0
/*
 * __win_fs_remove --
 *	Remove a file.
 */
static int
__win_fs_remove(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *name, uint32_t flags)
{
	DWORD windows_error;
	WT_DECL_ITEM(name_wide);
	WT_DECL_RET;
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);
	WT_UNUSED(flags);

	session = (WT_SESSION_IMPL *)wt_session;

	WT_RET(__wt_to_utf16_string(session, name, &name_wide));

	if (DeleteFileW(name_wide->data) == FALSE) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s: file-remove: DeleteFileW: %s",
		    name, __wt_formatmessage(session, windows_error));
		WT_ERR(ret);
	}

err:	__wt_scr_free(session, &name_wide);
	return (ret);
}
Beispiel #5
0
/*
 * __wt_dlopen --
 *	Open a dynamic library.
 */
int
__wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp)
{
	DWORD windows_error;
	WT_DECL_RET;
	WT_DLH *dlh;

	WT_RET(__wt_calloc_one(session, &dlh));
	WT_ERR(__wt_strdup(session, path, &dlh->name));
	WT_ERR(__wt_strdup(session, path == NULL ? "local" : path, &dlh->name));

	/* NULL means load from the current binary */
	if (path == NULL) {
		if (GetModuleHandleExA(
		    0, NULL, (HMODULE *)&dlh->handle) == FALSE) {
			windows_error = __wt_getlasterror();
			__wt_errx(session,
			    "GetModuleHandleEx: %s: %s",
			    path, __wt_formatmessage(session, windows_error));
			WT_ERR(__wt_map_windows_error(windows_error));
		}
	} else {
		// TODO: load dll here
		DebugBreak();
	}

	*dlhp = dlh;
	if (0) {
err:		__wt_free(session, dlh->name);
		__wt_free(session, dlh);
	}
	return (ret);
}
Beispiel #6
0
/*
 * __wt_win_fs_size --
 *	Get the size of a file in bytes, by file name.
 */
int
__wt_win_fs_size(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *name, wt_off_t *sizep)
{
	DWORD windows_error;
	WIN32_FILE_ATTRIBUTE_DATA data;
	WT_DECL_ITEM(name_wide);
	WT_DECL_RET;
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);
	session = (WT_SESSION_IMPL *)wt_session;

	WT_RET(__wt_to_utf16_string(session, name, &name_wide));

	if (GetFileAttributesExW(
	    name_wide->data, GetFileExInfoStandard, &data) == 0) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s: file-size: GetFileAttributesEx: %s",
		    name, __wt_formatmessage(session, windows_error));
		WT_ERR(ret);
	}

	*sizep = ((int64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow;

err:	__wt_scr_free(session, &name_wide);
	return (ret);
}
Beispiel #7
0
/*
 * __win_file_size --
 *	Get the size of a file in bytes, by file handle.
 */
static int
__win_file_size(
    WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t *sizep)
{
	DWORD windows_error;
	LARGE_INTEGER size;
	WT_DECL_RET;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	if (GetFileSizeEx(win_fh->filehandle, &size) != 0) {
		*sizep = size.QuadPart;
		return (0);
	}

	windows_error = __wt_getlasterror();
	ret = __wt_map_windows_error(windows_error);
	__wt_err(session, ret,
	    "%s: handle-size: GetFileSizeEx: %s",
	    file_handle->name, __wt_formatmessage(session, windows_error));
	return (ret);
}
Beispiel #8
0
/*
 * __win_fs_rename --
 *	Rename a file.
 */
static int
__win_fs_rename(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags)
{
	DWORD windows_error;
	WT_DECL_RET;
	WT_DECL_ITEM(from_wide);
	WT_DECL_ITEM(to_wide);
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);
	WT_UNUSED(flags);
	session = (WT_SESSION_IMPL *)wt_session;

	WT_ERR(__wt_to_utf16_string(session, from, &from_wide));
	WT_ERR(__wt_to_utf16_string(session, to, &to_wide));

	/*
	 * Check if file exists since Windows does not override the file if
	 * it exists.
	 */
	if (GetFileAttributesW(to_wide->data) != INVALID_FILE_ATTRIBUTES)
		if (DeleteFileW(to_wide->data) == FALSE) {
			windows_error = __wt_getlasterror();
			__wt_errx(session,
			    "%s: file-rename: DeleteFileW: %s",
			    to, __wt_formatmessage(session, windows_error));
			WT_ERR(__wt_map_windows_error(windows_error));
		}

	if (MoveFileW(from_wide->data, to_wide->data) == FALSE) {
		windows_error = __wt_getlasterror();
		__wt_errx(session,
		    "%s to %s: file-rename: MoveFileW: %s",
		    from, to, __wt_formatmessage(session, windows_error));
		WT_ERR(__wt_map_windows_error(windows_error));
	}

err:	__wt_scr_free(session, &from_wide);
	__wt_scr_free(session, &to_wide);
	return (ret);
}
Beispiel #9
0
/*
 * __win_file_close --
 *	ANSI C close.
 */
static int
__win_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
{
	DWORD windows_error;
	WT_DECL_RET;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	/*
	 * Close the primary and secondary handles.
	 *
	 * We don't open Windows system handles when opening directories for
	 * flushing, as it's not necessary (or possible) to flush a directory
	 * on Windows. Confirm the file handle is open before closing it.
	 */
	if (win_fh->filehandle != INVALID_HANDLE_VALUE &&
	    CloseHandle(win_fh->filehandle) == 0) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s: handle-close: CloseHandle: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
	}

	if (win_fh->filehandle_secondary != INVALID_HANDLE_VALUE &&
	    CloseHandle(win_fh->filehandle_secondary) == 0) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s: handle-close: secondary: CloseHandle: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
	}

	__wt_free(session, file_handle->name);
	__wt_free(session, win_fh);
	return (ret);
}
Beispiel #10
0
/*
 * __win_file_lock --
 *	Lock/unlock a file.
 */
static int
__win_file_lock(
    WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, bool lock)
{
	DWORD windows_error;
	WT_DECL_RET;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	/*
	 * WiredTiger requires this function be able to acquire locks past
	 * the end of file.
	 *
	 * http://msdn.microsoft.com/
	 *    en-us/library/windows/desktop/aa365202%28v=vs.85%29.aspx
	 *
	 * You can lock bytes that are beyond the end of the current file.
	 * This is useful to coordinate adding records to the end of a file.
	 */
	if (lock) {
		if (LockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) {
			windows_error = __wt_getlasterror();
			ret = __wt_map_windows_error(windows_error);
			__wt_err(session, ret,
			    "%s: handle-lock: LockFile: %s",
			    file_handle->name,
			    __wt_formatmessage(session, windows_error));
		}
	} else
		if (UnlockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) {
			windows_error = __wt_getlasterror();
			ret = __wt_map_windows_error(windows_error);
			__wt_err(session, ret,
			    "%s: handle-lock: UnlockFile: %s",
			    file_handle->name,
			    __wt_formatmessage(session, windows_error));
		}
	return (ret);
}
Beispiel #11
0
/*
 * __wt_thread_join --
 *	Wait for a thread of control to exit.
 */
int
__wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t *tid)
{
	DWORD windows_error;

	/* Only attempt to join if thread was created successfully */
	if (!tid->created)
		return (0);
	tid->created = false;

	/*
	 * Joining a thread isn't a memory barrier, but WiredTiger commonly
	 * sets flags and or state and then expects worker threads to halt.
	 * Include a barrier to ensure safety in those cases.
	 */
	WT_FULL_BARRIER();

	if ((windows_error =
	    WaitForSingleObject(tid->id, INFINITE)) != WAIT_OBJECT_0) {
		if (windows_error == WAIT_FAILED)
			windows_error = __wt_getlasterror();
		__wt_errx(session, "thread join: WaitForSingleObject: %s",
		    __wt_formatmessage(session, windows_error));

		/* If we fail to wait, we will leak handles, do not continue. */
		return (WT_PANIC);
	}

	if (CloseHandle(tid->id) == 0) {
		windows_error = __wt_getlasterror();
		__wt_errx(session, "thread join: CloseHandle: %s",
		    __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}

	return (0);
}
Beispiel #12
0
/*
 * __win_file_read --
 *	Read a chunk.
 */
static int
__win_file_read(WT_FILE_HANDLE *file_handle,
    WT_SESSION *wt_session, wt_off_t offset, size_t len, void *buf)
{
	DWORD chunk, nr, windows_error;
	OVERLAPPED overlapped = { 0 };
	WT_DECL_RET;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;
	uint8_t *addr;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	nr = 0;

	/* Assert direct I/O is aligned and a multiple of the alignment. */
	WT_ASSERT(session,
	    !win_fh->direct_io ||
	    S2C(session)->buffer_alignment == 0 ||
	    (!((uintptr_t)buf &
	    (uintptr_t)(S2C(session)->buffer_alignment - 1)) &&
	    len >= S2C(session)->buffer_alignment &&
	    len % S2C(session)->buffer_alignment == 0));

	/* Break reads larger than 1GB into 1GB chunks. */
	for (addr = buf; len > 0; addr += nr, len -= (size_t)nr, offset += nr) {
		chunk = (DWORD)WT_MIN(len, WT_GIGABYTE);
		overlapped.Offset = UINT32_MAX & offset;
		overlapped.OffsetHigh = UINT32_MAX & (offset >> 32);

		if (!ReadFile(
		    win_fh->filehandle, addr, chunk, &nr, &overlapped)) {
			windows_error = __wt_getlasterror();
			ret = __wt_map_windows_error(windows_error);
			if (ret == WT_ERROR)
				F_SET(S2C(session), WT_CONN_DATA_CORRUPTION);
			__wt_err(session, ret,
			    "%s: handle-read: ReadFile: failed to read %lu "
			    "bytes at offset %" PRIuMAX ": %s",
			    file_handle->name, chunk, (uintmax_t)offset,
			    __wt_formatmessage(session, windows_error));
			return (ret);
		}
	}
	return (0);
}
Beispiel #13
0
/*
 * __wt_dlclose --
 *	Close a dynamic library
 */
int
__wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh)
{
	DWORD windows_error;
	WT_DECL_RET;

	if (FreeLibrary(dlh->handle) == FALSE) {
		windows_error = __wt_getlasterror();
		__wt_errx(session, "FreeLibrary: %s: %s",
		    dlh->name, __wt_formatmessage(session, windows_error));
		ret = __wt_map_windows_error(windows_error);
	}

	__wt_free(session, dlh->name);
	__wt_free(session, dlh);
	return (ret);
}
Beispiel #14
0
/*
 * __win_file_write --
 *	Write a chunk.
 */
static int
__win_file_write(WT_FILE_HANDLE *file_handle,
    WT_SESSION *wt_session, wt_off_t offset, size_t len, const void *buf)
{
	DWORD chunk, nw, windows_error;
	const uint8_t *addr;
	OVERLAPPED overlapped = { 0 };
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	nw = 0;

	/* Assert direct I/O is aligned and a multiple of the alignment. */
	WT_ASSERT(session,
	    !win_fh->direct_io ||
	    S2C(session)->buffer_alignment == 0 ||
	    (!((uintptr_t)buf &
	    (uintptr_t)(S2C(session)->buffer_alignment - 1)) &&
	    len >= S2C(session)->buffer_alignment &&
	    len % S2C(session)->buffer_alignment == 0));

	/* Break writes larger than 1GB into 1GB chunks. */
	for (addr = buf; len > 0; addr += nw, len -= (size_t)nw, offset += nw) {
		chunk = (DWORD)WT_MIN(len, WT_GIGABYTE);
		overlapped.Offset = UINT32_MAX & offset;
		overlapped.OffsetHigh = UINT32_MAX & (offset >> 32);

		if (!WriteFile(
		    win_fh->filehandle, addr, chunk, &nw, &overlapped)) {
			windows_error = __wt_getlasterror();
			__wt_errx(session,
			    "%s: handle-write: WriteFile: failed to write %lu "
			    "bytes at offset %" PRIuMAX ": %s",
			    file_handle->name, chunk, (uintmax_t)offset,
			    __wt_formatmessage(session, windows_error));
			return (__wt_map_windows_error(windows_error));
		}
	}
	return (0);
}
Beispiel #15
0
/*
 * __win_fs_remove --
 *	Remove a file.
 */
static int
__win_fs_remove(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *name, uint32_t flags)
{
	DWORD windows_error;
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);
	WT_UNUSED(flags);

	session = (WT_SESSION_IMPL *)wt_session;

	if (DeleteFileA(name) == FALSE) {
		windows_error = __wt_getlasterror();
		__wt_errx(session,
		    "%s: file-remove: DeleteFileA: %s",
		    name, __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}
	return (0);
}
Beispiel #16
0
/*
 * __win_fs_rename --
 *	Rename a file.
 */
static int
__win_fs_rename(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags)
{
	DWORD windows_error;
	WT_DECL_ITEM(from_wide);
	WT_DECL_ITEM(to_wide);
	WT_DECL_RET;
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);
	WT_UNUSED(flags);
	session = (WT_SESSION_IMPL *)wt_session;

	WT_ERR(__wt_to_utf16_string(session, from, &from_wide));
	WT_ERR(__wt_to_utf16_string(session, to, &to_wide));

	/*
	 * We want an atomic rename, but that's not guaranteed by MoveFileExW
	 * (or by any MSDN API). Don't set the MOVEFILE_COPY_ALLOWED flag to
	 * prevent the system from falling back to a copy and delete process.
	 * Do set the MOVEFILE_WRITE_THROUGH flag so the window is as small
	 * as possible, just in case. WiredTiger renames are done in a single
	 * directory and we expect that to be an atomic metadata update on any
	 * modern filesystem.
	 */
	if (MoveFileExW(from_wide->data, to_wide->data,
	    MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == FALSE) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s to %s: file-rename: MoveFileExW: %s",
		    from, to, __wt_formatmessage(session, windows_error));
		WT_ERR(ret);
	}

err:	__wt_scr_free(session, &from_wide);
	__wt_scr_free(session, &to_wide);
	return (ret);
}
Beispiel #17
0
/*
 * __wt_getenv --
 * 	Get a non-NULL, greater than zero-length environment variable.
 */
int
__wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp)
{
	DWORD size, windows_error;

	*envp = NULL;

	if ((size = GetEnvironmentVariableA(variable, NULL, 0)) <= 1)
		return (0);

	WT_RET(__wt_malloc(session, (size_t)size, envp));

	/* We expect the number of bytes not including nul terminator. */
	if (GetEnvironmentVariableA(variable, *envp, size) == size - 1)
		return (0);

	windows_error = __wt_getlasterror();
	__wt_errx(session,
	    "GetEnvironmentVariableA: %s: %s",
	    variable, __wt_formatmessage(session, windows_error));
	return (__wt_map_windows_error(windows_error));
}
Beispiel #18
0
/*
 * __wt_dlsym --
 *	Lookup a symbol in a dynamic library.
 */
int
__wt_dlsym(WT_SESSION_IMPL *session,
    WT_DLH *dlh, const char *name, bool fail, void *sym_ret)
{
	DWORD windows_error;
	void *sym;

	*(void **)sym_ret = NULL;

	sym = GetProcAddress(dlh->handle, name);
	if (sym == NULL && fail) {
		windows_error = __wt_getlasterror();
		__wt_errx(session,
		    "GetProcAddress: %s in %s: %s",
		    name, dlh->name,
		    __wt_formatmessage(session, windows_error));
		WT_RET(__wt_map_windows_error(windows_error));
	}

	*(void **)sym_ret = sym;
	return (0);
}
Beispiel #19
0
/*
 * __wt_getenv --
 * 	Get a non-NULL, greater than zero-length environment variable.
 */
int
__wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp)
{
    WT_DECL_RET;
    DWORD size;

    *envp = NULL;

    size = GetEnvironmentVariableA(variable, NULL, 0);
    if (size <= 1)
        return (WT_NOTFOUND);

    WT_RET(__wt_calloc(session, 1, size, envp));

    ret = GetEnvironmentVariableA(variable, *envp, size);
    /* We expect the number of bytes not including nul terminator. */
    if ((ret + 1) != size)
        WT_RET_MSG(session, __wt_getlasterror(),
                   "GetEnvironmentVariableA failed: %s", variable);

    return (0);
}
Beispiel #20
0
/*
 * __wt_win_fs_size --
 *	Get the size of a file in bytes, by file name.
 */
int
__wt_win_fs_size(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *name, wt_off_t *sizep)
{
	DWORD windows_error;
	WIN32_FILE_ATTRIBUTE_DATA data;
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);

	session = (WT_SESSION_IMPL *)wt_session;

	if (GetFileAttributesExA(name, GetFileExInfoStandard, &data) != 0) {
		*sizep =
		    ((int64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow;
		return (0);
	}

	windows_error = __wt_getlasterror();
	__wt_errx(session,
	    "%s: file-size: GetFileAttributesEx: %s",
	    name, __wt_formatmessage(session, windows_error));
	return (__wt_map_windows_error(windows_error));
}
Beispiel #21
0
/*
 * __wt_win_directory_list --
 *	Get a list of files from a directory, MSVC version.
 */
int
__wt_win_directory_list(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *directory,
    const char *prefix, char ***dirlistp, uint32_t *countp)
{
	DWORD windows_error;
	HANDLE findhandle;
	WIN32_FIND_DATAW finddata;
	WT_DECL_ITEM(pathbuf);
	WT_DECL_ITEM(file_utf8);
	WT_DECL_ITEM(pathbuf_wide);
	WT_DECL_ITEM(prefix_wide);
	WT_DECL_RET;
	WT_SESSION_IMPL *session;
	size_t dirallocsz, pathlen, prefix_widelen;
	uint32_t count;
	char *dir_copy, **entries;

	session = (WT_SESSION_IMPL *)wt_session;

	*dirlistp = NULL;
	*countp = 0;

	findhandle = INVALID_HANDLE_VALUE;
	dirallocsz = 0;
	entries = NULL;

	WT_ERR(__wt_strdup(session, directory, &dir_copy));
	pathlen = strlen(dir_copy);
	if (dir_copy[pathlen - 1] == '\\')
		dir_copy[pathlen - 1] = '\0';
	WT_ERR(__wt_scr_alloc(session, pathlen + 3, &pathbuf));
	WT_ERR(__wt_buf_fmt(session, pathbuf, "%s\\*", dir_copy));

	WT_ERR(__wt_to_utf16_string(session, pathbuf->data, &pathbuf_wide));
	WT_ERR(__wt_to_utf16_string(session, prefix, &prefix_wide));
	prefix_widelen = wcslen(prefix_wide->data);

	findhandle = FindFirstFileW(pathbuf_wide->data, &finddata);
	if (findhandle == INVALID_HANDLE_VALUE) {
		windows_error = __wt_getlasterror();
		__wt_errx(session,
		    "%s: directory-list: FindFirstFile: %s",
		    pathbuf->data, __wt_formatmessage(session, windows_error));
		WT_ERR(__wt_map_windows_error(windows_error));
	}

	count = 0;
	do {
		/*
		 * Skip . and ..
		 */
		if (wcscmp(finddata.cFileName, L".") == 0 ||
		    wcscmp(finddata.cFileName, L"..") == 0)
			continue;

		/* The list of files is optionally filtered by a prefix. */
		if (prefix != NULL &&
		    wcsncmp(finddata.cFileName, prefix_wide->data,
			prefix_widelen) != 0)
			continue;

		WT_ERR(__wt_realloc_def(
		    session, &dirallocsz, count + 1, &entries));

		WT_ERR(__wt_to_utf8_string(
		    session, finddata.cFileName, &file_utf8));
		WT_ERR(__wt_strdup(session, file_utf8->data, &entries[count]));
		++count;
		__wt_scr_free(session, &file_utf8);
	} while (FindNextFileW(findhandle, &finddata) != 0);

	*dirlistp = entries;
	*countp = count;

err:	if (findhandle != INVALID_HANDLE_VALUE)
		if (FindClose(findhandle) == 0) {
			windows_error = __wt_getlasterror();
			__wt_errx(session,
			    "%s: directory-list: FindClose: %s",
			    pathbuf->data,
			    __wt_formatmessage(session, windows_error));
			if (ret == 0)
				ret = __wt_map_windows_error(windows_error);
		}

	__wt_free(session, dir_copy);
	__wt_scr_free(session, &pathbuf);
	__wt_scr_free(session, &file_utf8);
	__wt_scr_free(session, &pathbuf_wide);
	__wt_scr_free(session, &prefix_wide);

	if (ret == 0)
		return (0);

	WT_TRET(__wt_win_directory_list_free(
	    file_system, wt_session, entries, count));

	WT_RET_MSG(session, ret,
	    "%s: directory-list, prefix \"%s\"",
	    directory, prefix == NULL ? "" : prefix);
}
Beispiel #22
0
/*
 * __wt_cond_wait_signal --
 *	Wait on a mutex, optionally timing out.  If we get it
 *	before the time out period expires, let the caller know.
 */
int
__wt_cond_wait_signal(
    WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled)
{
    BOOL sleepret;
    DWORD milliseconds, windows_error;
    bool locked;
    uint64_t milliseconds64;

    locked = false;

    /* Fast path if already signalled. */
    *signalled = true;
    if (__wt_atomic_addi32(&cond->waiters, 1) == 0)
        return (0);

    /*
     * !!!
     * This function MUST handle a NULL session handle.
     */
    if (session != NULL) {
        WT_RET(__wt_verbose(session, WT_VERB_MUTEX,
                            "wait %s cond (%p)", cond->name, cond));
        WT_STAT_FAST_CONN_INCR(session, cond_wait);
    }

    EnterCriticalSection(&cond->mtx);
    locked = true;

    if (usecs > 0) {
        milliseconds64 = usecs / 1000;

        /*
         * Check for 32-bit unsigned integer overflow
         * INFINITE is max unsigned int on Windows
         */
        if (milliseconds64 >= INFINITE)
            milliseconds64 = INFINITE - 1;
        milliseconds = (DWORD)milliseconds64;

        /*
         * 0 would mean the CV sleep becomes a TryCV which we do not
         * want
         */
        if (milliseconds == 0)
            milliseconds = 1;

        sleepret = SleepConditionVariableCS(
                       &cond->cond, &cond->mtx, milliseconds);
    } else
        sleepret = SleepConditionVariableCS(
                       &cond->cond, &cond->mtx, INFINITE);

    /*
     * SleepConditionVariableCS returns non-zero on success, 0 on timeout
     * or failure.
     */
    if (sleepret == 0) {
        windows_error = __wt_getlasterror();
        if (windows_error == ERROR_TIMEOUT) {
            *signalled = false;
            sleepret = 1;
        }
    }

    (void)__wt_atomic_subi32(&cond->waiters, 1);

    if (locked)
        LeaveCriticalSection(&cond->mtx);

    if (sleepret != 0)
        return (0);

    __wt_errx(session, "SleepConditionVariableCS: %s",
              __wt_formatmessage(session, windows_error));
    return (__wt_map_windows_error(windows_error));
}
Beispiel #23
0
/*
 * __win_open_file --
 *	Open a file handle.
 */
static int
__win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
    const char *name, WT_FS_OPEN_FILE_TYPE file_type, uint32_t flags,
    WT_FILE_HANDLE **file_handlep)
{
	DWORD dwCreationDisposition, windows_error;
	WT_CONNECTION_IMPL *conn;
	WT_DECL_ITEM(name_wide);
	WT_DECL_RET;
	WT_FILE_HANDLE *file_handle;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;
	int desired_access, f;

	WT_UNUSED(file_system);
	session = (WT_SESSION_IMPL *)wt_session;
	conn = S2C(session);
	*file_handlep = NULL;

	WT_RET(__wt_calloc_one(session, &win_fh));
	win_fh->direct_io = false;

	/* Set up error handling. */
	win_fh->filehandle =
	    win_fh->filehandle_secondary = INVALID_HANDLE_VALUE;

	WT_ERR(__wt_to_utf16_string(session, name, &name_wide));

	/*
	 * Opening a file handle on a directory is only to support filesystems
	 * that require a directory sync for durability, and Windows doesn't
	 * require that functionality: create an empty WT_FH structure with
	 * invalid handles.
	 */
	if (file_type == WT_FS_OPEN_FILE_TYPE_DIRECTORY)
		goto directory_open;

	desired_access = GENERIC_READ;
	if (!LF_ISSET(WT_FS_OPEN_READONLY))
		desired_access |= GENERIC_WRITE;

	/*
	 * Security:
	 * The application may spawn a new process, and we don't want another
	 * process to have access to our file handles.
	 *
	 * TODO: Set tighter file permissions but set bInheritHandle to false
	 * to prevent inheritance
	 */
	f = FILE_ATTRIBUTE_NORMAL;

	dwCreationDisposition = 0;
	if (LF_ISSET(WT_FS_OPEN_CREATE)) {
		dwCreationDisposition = CREATE_NEW;
		if (LF_ISSET(WT_FS_OPEN_EXCLUSIVE))
			dwCreationDisposition = CREATE_ALWAYS;
	} else
		dwCreationDisposition = OPEN_EXISTING;

	/* Direct I/O. */
	if (LF_ISSET(WT_FS_OPEN_DIRECTIO)) {
		f |= FILE_FLAG_NO_BUFFERING;
		win_fh->direct_io = true;
	}

	/* FILE_FLAG_WRITE_THROUGH does not require aligned buffers */
	if (FLD_ISSET(conn->write_through, file_type))
		f |= FILE_FLAG_WRITE_THROUGH;

	if (file_type == WT_FS_OPEN_FILE_TYPE_LOG &&
	    FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC))
		f |= FILE_FLAG_WRITE_THROUGH;

	/* If the user indicated a random workload, disable read-ahead. */
	if (file_type == WT_FS_OPEN_FILE_TYPE_DATA &&
	    LF_ISSET(WT_FS_OPEN_ACCESS_RAND))
		f |= FILE_FLAG_RANDOM_ACCESS;

	/* If the user indicated a sequential workload, set that. */
	if (file_type == WT_FS_OPEN_FILE_TYPE_DATA &&
	    LF_ISSET(WT_FS_OPEN_ACCESS_SEQ))
		f |= FILE_FLAG_SEQUENTIAL_SCAN;

	win_fh->filehandle = CreateFileW(name_wide->data, desired_access,
	    FILE_SHARE_READ | FILE_SHARE_WRITE,
	    NULL, dwCreationDisposition, f, NULL);
	if (win_fh->filehandle == INVALID_HANDLE_VALUE) {
		if (LF_ISSET(WT_FS_OPEN_CREATE) &&
		    GetLastError() == ERROR_FILE_EXISTS)
			win_fh->filehandle = CreateFileW(name_wide->data,
			    desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE,
			    NULL, OPEN_EXISTING, f, NULL);
		if (win_fh->filehandle == INVALID_HANDLE_VALUE) {
			windows_error = __wt_getlasterror();
			ret = __wt_map_windows_error(windows_error);
			__wt_err(session, ret,
			    win_fh->direct_io ?
			    "%s: handle-open: CreateFileW: failed with direct "
			    "I/O configured, some filesystem types do not "
			    "support direct I/O: %s" :
			    "%s: handle-open: CreateFileW: %s",
			    name, __wt_formatmessage(session, windows_error));
			WT_ERR(ret);
		}
	}

	/*
	 * Open a second handle to file to support file extension/truncation
	 * concurrently with reads on the file. Writes would also move the
	 * file pointer.
	 */
	if (!LF_ISSET(WT_FS_OPEN_READONLY)) {
		win_fh->filehandle_secondary = CreateFileW(name_wide->data,
		    desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE,
		    NULL, OPEN_EXISTING, f, NULL);
		if (win_fh->filehandle_secondary == INVALID_HANDLE_VALUE) {
			windows_error = __wt_getlasterror();
			ret = __wt_map_windows_error(windows_error);
			__wt_err(session, ret,
			    "%s: handle-open: Creatively: secondary: %s",
			    name, __wt_formatmessage(session, windows_error));
			WT_ERR(ret);
		}
	}

directory_open:
	/* Initialize public information. */
	file_handle = (WT_FILE_HANDLE *)win_fh;
	WT_ERR(__wt_strdup(session, name, &file_handle->name));

	file_handle->close = __win_file_close;
	file_handle->fh_lock = __win_file_lock;
#ifdef WORDS_BIGENDIAN
	/*
	 * The underlying objects are little-endian, mapping objects isn't
	 * currently supported on big-endian systems.
	 */
#else
	file_handle->fh_map = __wt_win_map;
	file_handle->fh_unmap = __wt_win_unmap;
#endif
	file_handle->fh_read = __win_file_read;
	file_handle->fh_size = __win_file_size;
	file_handle->fh_sync = __win_file_sync;

	/* Extend and truncate share the same implementation. */
	file_handle->fh_extend = __win_file_set_end;
	file_handle->fh_truncate = __win_file_set_end;

	file_handle->fh_write = __win_file_write;

	*file_handlep = file_handle;

	__wt_scr_free(session, &name_wide);
	return (0);

err:	__wt_scr_free(session, &name_wide);
	WT_TRET(__win_file_close((WT_FILE_HANDLE *)win_fh, wt_session));
	return (ret);
}
Beispiel #24
0
/*
 * __wt_cond_wait_signal --
 *	Wait on a mutex, optionally timing out.  If we get it before the time
 * out period expires, let the caller know.
 */
void
__wt_cond_wait_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond,
    uint64_t usecs, bool (*run_func)(WT_SESSION_IMPL *), bool *signalled)
{
	BOOL sleepret;
	DWORD milliseconds, windows_error;
	bool locked;
	uint64_t milliseconds64;

	locked = false;

	/* Fast path if already signalled. */
	*signalled = true;
	if (__wt_atomic_addi32(&cond->waiters, 1) == 0)
		return;

	__wt_verbose(session, WT_VERB_MUTEX, "wait %s", cond->name);
	WT_STAT_CONN_INCR(session, cond_wait);

	EnterCriticalSection(&cond->mtx);
	locked = true;

	/*
	 * It's possible to race with threads waking us up. That's not a problem
	 * if there are multiple wakeups because the next wakeup will get us, or
	 * if we're only pausing for a short period. It's a problem if there's
	 * only a single wakeup, our waker is likely waiting for us to exit.
	 * After acquiring the mutex (so we're guaranteed to be awakened by any
	 * future wakeup call), optionally check if we're OK to keep running.
	 * This won't ensure our caller won't just loop and call us again, but
	 * at least it's not our fault.
	 *
	 * Assert we're not waiting longer than a second if not checking the
	 * run status.
	 */
	WT_ASSERT(session, run_func != NULL || usecs <= WT_MILLION);

	if (run_func != NULL && !run_func(session))
		goto skipping;

	if (usecs > 0) {
		milliseconds64 = usecs / WT_THOUSAND;

		/*
		 * Check for 32-bit unsigned integer overflow
		 * INFINITE is max unsigned int on Windows
		 */
		if (milliseconds64 >= INFINITE)
			milliseconds64 = INFINITE - 1;
		milliseconds = (DWORD)milliseconds64;

		/*
		 * 0 would mean the CV sleep becomes a TryCV which we do not
		 * want
		 */
		if (milliseconds == 0)
			milliseconds = 1;

		sleepret = SleepConditionVariableCS(
		    &cond->cond, &cond->mtx, milliseconds);
	} else
		sleepret = SleepConditionVariableCS(
		    &cond->cond, &cond->mtx, INFINITE);

	/*
	 * SleepConditionVariableCS returns non-zero on success, 0 on timeout
	 * or failure.
	 */
	if (sleepret == 0) {
		windows_error = __wt_getlasterror();
		if (windows_error == ERROR_TIMEOUT) {
skipping:		*signalled = false;
			sleepret = 1;
		}
	}

	(void)__wt_atomic_subi32(&cond->waiters, 1);

	if (locked)
		LeaveCriticalSection(&cond->mtx);

	if (sleepret != 0)
		return;

	__wt_err(session,
	    __wt_map_windows_error(windows_error),
	    "SleepConditionVariableCS: %s: %s",
	    cond->name, __wt_formatmessage(session, windows_error));
	WT_PANIC_MSG(session, __wt_map_windows_error(windows_error),
	    "SleepConditionVariableCS: %s", cond->name);
}
Beispiel #25
-1
/*
 * __win_file_set_end --
 *	Truncate or extend a file.
 */
static int
__win_file_set_end(
    WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t len)
{
	DWORD windows_error;
	LARGE_INTEGER largeint;
	WT_DECL_RET;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;

	win_fh = (WT_FILE_HANDLE_WIN *)file_handle;
	session = (WT_SESSION_IMPL *)wt_session;

	largeint.QuadPart = len;

	if (win_fh->filehandle_secondary == INVALID_HANDLE_VALUE)
		WT_RET_MSG(session, EINVAL,
		    "%s: handle-set-end: no secondary handle",
		    file_handle->name);

	if (SetFilePointerEx(win_fh->filehandle_secondary,
	    largeint, NULL, FILE_BEGIN) == FALSE) {
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s: handle-set-end: SetFilePointerEx: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
		return (ret);
	}

	if (SetEndOfFile(win_fh->filehandle_secondary) == FALSE) {
		if (GetLastError() == ERROR_USER_MAPPED_FILE)
			return (__wt_set_return(session, EBUSY));
		windows_error = __wt_getlasterror();
		ret = __wt_map_windows_error(windows_error);
		__wt_err(session, ret,
		    "%s: handle-set-end: SetEndOfFile: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
		return (ret);
	}
	return (0);
}