예제 #1
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);
}
예제 #2
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);
}
예제 #3
0
파일: os_fs.c 프로젝트: Machyne/mongo
/*
 * __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);
}
예제 #4
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);
}
예제 #5
0
/*
 * __win_fs_exist --
 *	Return if the file exists.
 */
static int
__win_fs_exist(WT_FILE_SYSTEM *file_system,
    WT_SESSION *wt_session, const char *name, bool *existp)
{
	WT_DECL_ITEM(name_wide);
	WT_SESSION_IMPL *session;

	WT_UNUSED(file_system);

	session = (WT_SESSION_IMPL *)wt_session;
	*existp = false;

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

	if (GetFileAttributesW(name_wide->data) != INVALID_FILE_ATTRIBUTES)
		*existp = true;

	__wt_scr_free(session, &name_wide);
	return (0);
}
예제 #6
0
파일: os_dir.c 프로젝트: ksuarz/mongo
/*
 * __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);
}
예제 #7
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);
}