コード例 #1
0
ファイル: os_rename.c プロジェクト: BobbWu/wiredtiger
/*
 * __wt_rename --
 *	Rename a file.
 */
int
__wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
{
	WT_DECL_RET;
	char *from_path, *to_path;

	WT_RET(__wt_verbose(
	    session, WT_VERB_FILEOPS, "rename %s to %s", from, to));

	WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_READONLY));
	from_path = to_path = NULL;

	WT_RET(__wt_filename(session, from, &from_path));
	WT_TRET(__wt_filename(session, to, &to_path));

	if (ret == 0)
		WT_SYSCALL_RETRY(rename(from_path, to_path), ret);

	__wt_free(session, from_path);
	__wt_free(session, to_path);

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

	WT_RET_MSG(session, ret, "rename %s to %s", from, to);
}
コード例 #2
0
ファイル: os_filesize.c プロジェクト: Zhangwusheng/wiredtiger
/*
 * __wt_filesize_name --
 *	Return the size of a file in bytes, given a file name.
 */
int
__wt_filesize_name(WT_SESSION_IMPL *session,
    const char *filename, bool silent, wt_off_t *sizep)
{
	struct stat sb;
	WT_DECL_RET;
	char *path;

	WT_RET(__wt_filename(session, filename, &path));

	WT_SYSCALL_RETRY(stat(path, &sb), ret);

	__wt_free(session, path);

	if (ret == 0) {
		*sizep = sb.st_size;
		return (0);
	}

	/*
	 * Some callers of this function expect failure if the file doesn't
	 * exist, and don't want an error message logged.
	 */
	if (!silent)
		WT_RET_MSG(session, ret, "%s: fstat", filename);
	return (ret);
}
コード例 #3
0
ファイル: cur_backup.c プロジェクト: mdkhaled/mongo
/*
 * __backup_file_create --
 *	Create the meta-data backup file.
 */
static int
__backup_file_create(
    WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, int incremental)
{
	WT_DECL_RET;
	char *path;

	/* Open the hot backup file. */
	if (incremental)
		WT_RET(__wt_filename(session, WT_INCREMENTAL_BACKUP, &path));
	else
		WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path));
	WT_ERR_TEST((cb->bfp = fopen(path, "w")) == NULL, __wt_errno());

err:	__wt_free(session, path);
	return (ret);
}
コード例 #4
0
ファイル: os_rename.c プロジェクト: zinuyasha/wiredtiger
/*
 * __wt_rename --
 *	Rename a file.
 */
int
__wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
{
	int ret;
	const char *from_path, *to_path;

	WT_VERBOSE(session, fileops, "rename %s to %s", from, to);

	WT_RET(__wt_filename(session, from, &from_path));
	WT_RET(__wt_filename(session, to, &to_path));

	WT_SYSCALL_RETRY(rename(from_path, to_path), ret);

	__wt_free(session, from_path);
	__wt_free(session, to_path);

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

	WT_RET_MSG(session, ret, "rename %s to %s", from, to);
}
コード例 #5
0
ファイル: meta_turtle.c プロジェクト: RedSunCMX/wiredtiger
/*
 * __wt_turtle_read --
 *	Read the turtle file.
 */
int
__wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **valuep)
{
	FILE *fp;
	WT_DECL_ITEM(buf);
	WT_DECL_RET;
	int match;
	char *path;

	*valuep = NULL;

	fp = NULL;
	path = NULL;

	/*
	 * Open the turtle file; there's one case where we won't find the turtle
	 * file, yet still succeed.  We create the metadata file before creating
	 * the turtle file, and that means returning the default configuration
	 * string for the metadata file.
	 */
	WT_RET(__wt_filename(session, WT_METADATA_TURTLE, &path));
	if ((fp = fopen(path, "r")) == NULL)
		ret = __wt_errno();
	__wt_free(session, path);
	if (fp == NULL)
		return (strcmp(key, WT_METAFILE_URI) == 0 ?
		    __metadata_config(session, valuep) : ret);

	/* Search for the key. */
	WT_ERR(__wt_scr_alloc(session, 512, &buf));
	for (match = 0;;) {
		WT_ERR(__wt_getline(session, buf, fp));
		if (buf->size == 0)
			WT_ERR(WT_NOTFOUND);
		if (strcmp(key, buf->data) == 0)
			match = 1;

		/* Key matched: read the subsequent line for the value. */
		WT_ERR(__wt_getline(session, buf, fp));
		if (buf->size == 0)
			WT_ERR(__wt_illegal_value(session, WT_METADATA_TURTLE));
		if (match)
			break;
	}

	/* Copy the value for the caller. */
	WT_ERR(__wt_strdup(session, buf->data, valuep));

err:	if (fp != NULL)
		WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno());
	__wt_scr_free(&buf);
	return (ret);
}
コード例 #6
0
ファイル: meta_turtle.c プロジェクト: qixin/wiredtiger
/*
 * __wt_meta_turtle_read --
 *	Read the turtle file.
 */
int
__wt_meta_turtle_read(
    WT_SESSION_IMPL *session, const char *key, const char **valuep)
{
	FILE *fp;
	WT_DECL_RET;
	const char *path;
	char *p, line[1024];

	fp = NULL;
	path = NULL;

	/* Open the turtle file. */
	WT_RET(__wt_filename(session, WT_METADATA_TURTLE, &path));
	WT_ERR_TEST((fp = fopen(path, "r")) == NULL, WT_NOTFOUND);

	/* Search for the key. */
	ret = WT_NOTFOUND;
	while (fgets(line, sizeof(line), fp) != NULL) {
		if ((p = strchr(line, '\n')) == NULL)
			goto format;
		*p = '\0';
		if (strcmp(key, line) == 0)
			ret = 0;

		/* Key matched: read the subsequent line for the value. */
		if (fgets(line, sizeof(line), fp) == NULL)
			goto format;
		if ((p = strchr(line, '\n')) == NULL)
			goto format;
		*p = '\0';
		if (ret == 0)
			break;
	}

	/* Check for an I/O error. */
	if (ferror(fp))
		WT_ERR(__wt_errno());
	WT_ERR(ret);

	/* Successful: copy the value for the caller. */
	WT_ERR(__wt_strdup(session, line, valuep));

	if (0) {
format:		return (__wt_illegal_value(session, WT_METADATA_TURTLE));
	}

err:	if (fp != NULL)
		WT_TRET(fclose(fp));
	__wt_free(session, path);
	return (ret);
}
コード例 #7
0
ファイル: os_rename.c プロジェクト: 3rf/mongo
/*
 * __wt_rename --
 *	Rename a file.
 */
int
__wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
{
	WT_DECL_RET;
	uint32_t lasterror;
	char *from_path, *to_path;

	WT_RET(__wt_verbose(
		session, WT_VERB_FILEOPS, "rename %s to %s", from, to));

	from_path = to_path = NULL;

	WT_RET(__wt_filename(session, from, &from_path));
	WT_TRET(__wt_filename(session, to, &to_path));

	/*
	 * Check if file exists since Windows does not override the file if
	 * it exists.
	 */
	if ((ret = GetFileAttributesA(to_path)) != INVALID_FILE_ATTRIBUTES) {
		if ((ret = DeleteFileA(to_path)) == FALSE) {
			lasterror = GetLastError();
			goto err;
		}
	}

	if ((MoveFileA(from_path, to_path)) == FALSE)
		lasterror = GetLastError();

err:
	__wt_free(session, from_path);
	__wt_free(session, to_path);

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

	WT_RET_MSG(session, lasterror, "MoveFile %s to %s", from, to);
}
コード例 #8
0
ファイル: os_rename.c プロジェクト: rain10154/wiredtiger
/*调用rename系统调用*/
int __wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to)
{
	WT_DECL_RET;
	char *from_path, *to_path;

	WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "rename %s to %s", from, to));

	from_path = to_path = NULL;

	/*对路劲进行校验,如果不合法路径,直接返回*/
	WT_RET(__wt_filename(session, from, &from_path));
	WT_TRET(__wt_filename(session, to, &to_path));

	if (ret == 0)
		WT_SYSCALL_RETRY(rename(from_path, to_path), ret);

	__wt_free(session, from_path);
	__wt_free(session, to_path);

	if(ret == 0)
		return 0;

	WT_RET_MSG(session, ret, "rename %s to %s", from, to);
}
コード例 #9
0
ファイル: meta_turtle.c プロジェクト: RedSunCMX/wiredtiger
/*
 * __wt_turtle_update --
 *	Update the turtle file.
 */
int
__wt_turtle_update(
    WT_SESSION_IMPL *session, const char *key,  const char *value)
{
	FILE *fp;
	WT_DECL_RET;
	int vmajor, vminor, vpatch;
	const char *version;
	char *path;

	fp = NULL;
	path = NULL;

	/*
	 * Create the turtle setup file: we currently re-write it from scratch
	 * every time.
	 */
	WT_RET(__wt_filename(session, WT_METADATA_TURTLE_SET, &path));
	if ((fp = fopen(path, "w")) == NULL)
		ret = __wt_errno();
	__wt_free(session, path);
	if (fp == NULL)
		return (ret);

	version = wiredtiger_version(&vmajor, &vminor, &vpatch);
	WT_ERR_TEST((fprintf(fp,
	    "%s\n%s\n%s\n" "major=%d,minor=%d,patch=%d\n%s\n%s\n",
	    WT_METADATA_VERSION_STR, version,
	    WT_METADATA_VERSION, vmajor, vminor, vpatch,
	    key, value) < 0), __wt_errno());

	ret = fclose(fp);
	fp = NULL;
	WT_ERR_TEST(ret == EOF, __wt_errno());

	WT_ERR(
	    __wt_rename(session, WT_METADATA_TURTLE_SET, WT_METADATA_TURTLE));

	if (0) {
err:		WT_TRET(__wt_remove(session, WT_METADATA_TURTLE_SET));
	}

	if  (fp != NULL)
		WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno());
	return (ret);
}
コード例 #10
0
ファイル: meta_table.c プロジェクト: umerazad/wiredtiger
/*
 * __wt_metadata_load_backup --
 *	Load the contents of any hot backup file.
 */
int
__wt_metadata_load_backup(WT_SESSION_IMPL *session)
{
	FILE *fp;
	WT_DECL_ITEM(key);
	WT_DECL_ITEM(value);
	WT_DECL_RET;
	const char *path;

	fp = NULL;
	path = NULL;

	/* Look for a hot backup file: if we find it, load it. */
	WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path));
	if ((fp = fopen(path, "r")) == NULL) {
		__wt_free(session, path);
		return (0);
	}

	/* Read line pairs and load them into the metadata file. */
	WT_ERR(__wt_scr_alloc(session, 512, &key));
	WT_ERR(__wt_scr_alloc(session, 512, &value));
	for (;;) {
		WT_ERR(__wt_getline(session, key, fp));
		if (key->size == 0)
			break;
		WT_ERR(__wt_getline(session, value, fp));
		if (value->size == 0)
			WT_ERR(__wt_illegal_value(session, WT_METADATA_BACKUP));
		WT_ERR(__wt_metadata_update(session, key->data, value->data));
	}

	/* Remove the hot backup file, it's only read (successfully) once. */
	WT_ERR(__wt_remove(session, WT_METADATA_BACKUP));

err:	if (fp != NULL)
		WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno());
	if (path != NULL)
		__wt_free(session, path);
	__wt_scr_free(&key);
	__wt_scr_free(&value);
	return (ret);
}
コード例 #11
0
ファイル: os_stdio.c プロジェクト: 7segments/mongo-1
/*
 * __wt_fopen --
 *	Open a FILE handle.
 */
int
__wt_fopen(WT_SESSION_IMPL *session,
    const char *name, WT_FHANDLE_MODE mode_flag, u_int flags, FILE **fpp)
{
	WT_DECL_RET;
	const char *mode, *path;
	char *pathbuf;

	WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: fopen", name));

	pathbuf = NULL;
	if (LF_ISSET(WT_FOPEN_FIXED))
		path = name;
	else {
		WT_RET(__wt_filename(session, name, &pathbuf));
		path = pathbuf;
	}

	mode = NULL;
	switch (mode_flag) {
	case WT_FHANDLE_APPEND:
		mode = WT_FOPEN_APPEND;
		break;
	case WT_FHANDLE_READ:
		mode = WT_FOPEN_READ;
		break;
	case WT_FHANDLE_WRITE:
		mode = WT_FOPEN_WRITE;
		break;
	}
	*fpp = fopen(path, mode);
	if (*fpp == NULL)
		ret = __wt_errno();

	if (pathbuf != NULL)
		__wt_free(session, pathbuf);

	if (ret == 0)
		return (0);
	WT_RET_MSG(session, ret, "%s: fopen", name);
}
コード例 #12
0
ファイル: os_filesize.c プロジェクト: 7segments/mongo-1
/*
 * __wt_filesize_name --
 *	Return the size of a file in bytes, given a file name.
 */
int
__wt_filesize_name(
    WT_SESSION_IMPL *session, const char *filename, wt_off_t *sizep)
{
	struct stat sb;
	WT_DECL_RET;
	char *path;

	WT_RET(__wt_filename(session, filename, &path));

	WT_SYSCALL_RETRY(stat(path, &sb), ret);

	__wt_free(session, path);

	if (ret == 0) {
		*sizep = sb.st_size;
		return (0);
	}

	WT_RET_MSG(session, ret, "%s: fstat", filename);
}
コード例 #13
0
ファイル: os_remove.c プロジェクト: BobbWu/wiredtiger
/*
 * __wt_remove --
 *	Remove a file.
 */
int
__wt_remove(WT_SESSION_IMPL *session, const char *name)
{
	WT_DECL_RET;
	char *path;

	WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: remove", name));

	__remove_file_check(session, name);

	WT_RET(__wt_filename(session, name, &path));

	WT_SYSCALL_RETRY(remove(path), ret);

	__wt_free(session, path);

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

	WT_RET_MSG(session, ret, "%s: remove", name);
}
コード例 #14
0
ファイル: meta_turtle.c プロジェクト: RedSunCMX/wiredtiger
/*
 * __metadata_load_hot_backup --
 *	Load the contents of any hot backup file.
 */
static int
__metadata_load_hot_backup(WT_SESSION_IMPL *session)
{
	FILE *fp;
	WT_DECL_ITEM(key);
	WT_DECL_ITEM(value);
	WT_DECL_RET;
	char *path;

	fp = NULL;
	path = NULL;

	/* Look for a hot backup file: if we find it, load it. */
	WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path));
	fp = fopen(path, "r");
	__wt_free(session, path);
	if (fp == NULL)
		return (0);

	/* Read line pairs and load them into the metadata file. */
	WT_ERR(__wt_scr_alloc(session, 512, &key));
	WT_ERR(__wt_scr_alloc(session, 512, &value));
	for (;;) {
		WT_ERR(__wt_getline(session, key, fp));
		if (key->size == 0)
			break;
		WT_ERR(__wt_getline(session, value, fp));
		if (value->size == 0)
			WT_ERR(__wt_illegal_value(session, WT_METADATA_BACKUP));
		WT_ERR(__wt_metadata_update(session, key->data, value->data));
	}

	F_SET(S2C(session), WT_CONN_WAS_BACKUP);

err:	if (fp != NULL)
		WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno());
	__wt_scr_free(&key);
	__wt_scr_free(&value);
	return (ret);
}
コード例 #15
0
ファイル: os_filesize.c プロジェクト: 3rf/mongo
/*
 * __wt_filesize_name --
 *	Return the size of a file in bytes, given a file name.
 */
int
__wt_filesize_name(
    WT_SESSION_IMPL *session, const char *filename, wt_off_t *sizep)
{
	WT_DECL_RET;
	WIN32_FILE_ATTRIBUTE_DATA data;
	char *path;

	WT_RET(__wt_filename(session, filename, &path));

	ret = GetFileAttributesExA(path, GetFileExInfoStandard, &data);

	__wt_free(session, path);

	if (ret != 0) {
		*sizep =
		    ((int64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow;
		return (0);
	}

	WT_RET_MSG(session, __wt_errno(), "%s: GetFileAttributesEx", filename);
}
コード例 #16
0
ファイル: os_remove.c プロジェクト: BobbWu/wiredtiger
/*
 * __wt_remove --
 *	Remove a file.
 */
int
__wt_remove(WT_SESSION_IMPL *session, const char *name)
{
	WT_DECL_RET;
	char *path;
	uint32_t lasterror;

	WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: remove", name));

	__remove_file_check(session, name);

	WT_RET(__wt_filename(session, name, &path));

	if ((ret = DeleteFileA(path)) == FALSE)
		lasterror = __wt_errno();

	__wt_free(session, path);

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

	WT_RET_MSG(session, lasterror, "%s: remove", name);
}
コード例 #17
0
ファイル: os_exist.c プロジェクト: zinuyasha/wiredtiger
/*
 * __wt_exist --
 *	Return if the file exists.
 */
int
__wt_exist(WT_SESSION_IMPL *session, const char *filename, int *existp)
{
	const char *path;
	struct stat sb;
	int ret;

	WT_RET(__wt_filename(session, filename, &path));

	WT_SYSCALL_RETRY(stat(path, &sb), ret);

	__wt_free(session, path);

	if (ret == 0) {
		*existp = 1;
		return (0);
	}
	if (ret == ENOENT) {
		*existp = 0;
		return (0);
	}

	WT_RET_MSG(session, ret, "%s: fstat", filename);
}
コード例 #18
0
ファイル: os_exist.c プロジェクト: BobbWu/wiredtiger
/*
 * __wt_exist --
 *	Return if the file exists.
 */
int
__wt_exist(WT_SESSION_IMPL *session, const char *filename, bool *existp)
{
	struct stat sb;
	WT_DECL_RET;
	char *path;

	*existp = false;

	WT_RET(__wt_filename(session, filename, &path));

	WT_SYSCALL_RETRY(stat(path, &sb), ret);

	__wt_free(session, path);

	if (ret == 0) {
		*existp = true;
		return (0);
	}
	if (ret == ENOENT)
		return (0);

	WT_RET_MSG(session, ret, "%s: fstat", filename);
}
コード例 #19
0
ファイル: os_open.c プロジェクト: RolfAndreassen/wiredtiger
/*
 * __wt_open --
 *	Open a file handle.
 */
int
__wt_open(WT_SESSION_IMPL *session,
    const char *name, int ok_create, int exclusive, int dio_type, WT_FH **fhp)
{
	WT_CONNECTION_IMPL *conn;
	WT_DECL_RET;
	WT_FH *fh, *tfh;
	mode_t mode;
	int direct_io, f, fd, matched;
	const char *path;

	conn = S2C(session);
	fh = NULL;
	fd = -1;
	path = NULL;

	WT_VERBOSE_RET(session, fileops, "%s: open", name);

	/* Increment the reference count if we already have the file open. */
	matched = 0;
	__wt_spin_lock(session, &conn->fh_lock);
	TAILQ_FOREACH(tfh, &conn->fhqh, q)
		if (strcmp(name, tfh->name) == 0) {
			++tfh->refcnt;
			*fhp = tfh;
			matched = 1;
			break;
		}
	__wt_spin_unlock(session, &conn->fh_lock);
	if (matched)
		return (0);

	WT_RET(__wt_filename(session, name, &path));

	f = O_RDWR;
#ifdef O_BINARY
	/* Windows clones: we always want to treat the file as a binary. */
	f |= O_BINARY;
#endif
#ifdef O_CLOEXEC
	/*
	 * Security:
	 * The application may spawn a new process, and we don't want another
	 * process to have access to our file handles.
	 */
	f |= O_CLOEXEC;
#endif
#ifdef O_NOATIME
	/* Avoid updating metadata for read-only workloads. */
	if (dio_type == WT_FILE_TYPE_DATA)
		f |= O_NOATIME;
#endif

	if (ok_create) {
		f |= O_CREAT;
		if (exclusive)
			f |= O_EXCL;
		mode = 0666;
	} else
		mode = 0;

	direct_io = 0;
#ifdef O_DIRECT
	if (dio_type && FLD_ISSET(conn->direct_io, dio_type)) {
		f |= O_DIRECT;
		direct_io = 1;
	}
#endif
	if (dio_type == WT_FILE_TYPE_LOG &&
	    FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC))
#ifdef O_DSYNC
		f |= O_DSYNC;
#elif defined(O_SYNC)
		f |= O_SYNC;
#else
		WT_ERR_MSG(session, ENOTSUP,
		    "Unsupported log sync mode requested");
#endif
	WT_SYSCALL_RETRY(((fd = open(path, f, mode)) == -1 ? 1 : 0), ret);
	if (ret != 0)
		WT_ERR_MSG(session, ret,
		    direct_io ?
		    "%s: open failed with direct I/O configured, some "
		    "filesystem types do not support direct I/O" : "%s", path);

#if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
	/*
	 * Security:
	 * The application may spawn a new process, and we don't want another
	 * process to have access to our file handles.  There's an obvious
	 * race here, so we prefer the flag to open if available.
	 */
	if ((f = fcntl(fd, F_GETFD)) == -1 ||
	    fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1)
		WT_ERR_MSG(session, __wt_errno(), "%s: fcntl", name);
#endif

#if defined(HAVE_POSIX_FADVISE)
	/* Disable read-ahead on trees: it slows down random read workloads. */
	if (dio_type == WT_FILE_TYPE_DATA)
		WT_ERR(posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM));
#endif

	if (F_ISSET(conn, WT_CONN_CKPT_SYNC))
		WT_ERR(__open_directory_sync(session));

	WT_ERR(__wt_calloc(session, 1, sizeof(WT_FH), &fh));
	WT_ERR(__wt_strdup(session, name, &fh->name));
	fh->fd = fd;
	fh->refcnt = 1;
	fh->direct_io = direct_io;

	/* Set the file's size. */
	WT_ERR(__wt_filesize(session, fh, &fh->size));

	/* Configure file extension. */
	if (dio_type == WT_FILE_TYPE_DATA)
		fh->extend_len = conn->data_extend_len;

	/*
	 * Repeat the check for a match, but then link onto the database's list
	 * of files.
	 */
	matched = 0;
	__wt_spin_lock(session, &conn->fh_lock);
	TAILQ_FOREACH(tfh, &conn->fhqh, q)
		if (strcmp(name, tfh->name) == 0) {
			++tfh->refcnt;
			*fhp = tfh;
			matched = 1;
			break;
		}
	if (!matched) {
		TAILQ_INSERT_TAIL(&conn->fhqh, fh, q);
		WT_STAT_FAST_CONN_INCR(session, file_open);

		*fhp = fh;
	}
	__wt_spin_unlock(session, &conn->fh_lock);
	if (matched) {
err:		if (fh != NULL) {
			__wt_free(session, fh->name);
			__wt_free(session, fh);
		}
		if (fd != -1)
			(void)close(fd);
	}

	__wt_free(session, path);
	return (ret);
}
コード例 #20
0
ファイル: os_open.c プロジェクト: deepinit-arek/wiredtiger
/*
 * __wt_open --
 *	Open a file handle.
 */
int
__wt_open(WT_SESSION_IMPL *session,
    const char *name, int ok_create, int exclusive, int dio_type, WT_FH **fhp)
{
	DWORD dwCreationDisposition;
	HANDLE filehandle, filehandle_secondary;
	WT_CONNECTION_IMPL *conn;
	WT_DECL_RET;
	WT_FH *fh, *tfh;
	uint64_t bucket, hash;
	int direct_io, f, matched, share_mode;
	char *path;

	conn = S2C(session);
	fh = NULL;
	path = NULL;
	filehandle = INVALID_HANDLE_VALUE;
	filehandle_secondary = INVALID_HANDLE_VALUE;
	direct_io = 0;
	hash = __wt_hash_city64(name, strlen(name));
	bucket = hash % WT_HASH_ARRAY_SIZE;

	WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: open", name));

	/* Increment the reference count if we already have the file open. */
	matched = 0;
	__wt_spin_lock(session, &conn->fh_lock);
	SLIST_FOREACH(tfh, &conn->fhhash[bucket], l)
		if (strcmp(name, tfh->name) == 0) {
			++tfh->ref;
			*fhp = tfh;
			matched = 1;
			break;
		}
	__wt_spin_unlock(session, &conn->fh_lock);
	if (matched)
		return (0);

	/* For directories, create empty file handles with invalid handles */
	if (dio_type == WT_FILE_TYPE_DIRECTORY) {
		goto setupfh;
	}

	WT_RET(__wt_filename(session, name, &path));

	share_mode = FILE_SHARE_READ | FILE_SHARE_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 (ok_create) {
		dwCreationDisposition = CREATE_NEW;
		if (exclusive)
			dwCreationDisposition = CREATE_ALWAYS;
	} else
		dwCreationDisposition = OPEN_EXISTING;

	if (dio_type && FLD_ISSET(conn->direct_io, dio_type)) {
		f |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
		direct_io = 1;
	}

	if (dio_type == WT_FILE_TYPE_LOG &&
	    FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC)) {
		f |= FILE_FLAG_WRITE_THROUGH;
	}

	/* Disable read-ahead on trees: it slows down random read workloads. */
	if (dio_type == WT_FILE_TYPE_DATA ||
	    dio_type == WT_FILE_TYPE_CHECKPOINT)
		f |= FILE_FLAG_RANDOM_ACCESS;

	filehandle = CreateFileA(path,
				(GENERIC_READ | GENERIC_WRITE),
				share_mode,
				NULL,
				dwCreationDisposition,
				f,
				NULL);
	if (filehandle == INVALID_HANDLE_VALUE) {
		if (GetLastError() == ERROR_FILE_EXISTS && ok_create)
			filehandle = CreateFileA(path,
						(GENERIC_READ | GENERIC_WRITE),
						share_mode,
						NULL,
						OPEN_EXISTING,
						f,
						NULL);

		if (filehandle == INVALID_HANDLE_VALUE)
			WT_ERR_MSG(session, __wt_errno(),
			    direct_io ?
			    "%s: open failed with direct I/O configured, some "
			    "filesystem types do not support direct I/O" :
			    "%s", path);
	}

	/*
	 * Open a second handle to file to support allocation/truncation
	 * concurrently with reads on the file. Writes would also move the file
	 * pointer.
	 */
	filehandle_secondary = CreateFileA(path,
	    (GENERIC_READ | GENERIC_WRITE),
	    share_mode,
	    NULL,
	    OPEN_EXISTING,
	    f,
	    NULL);
	if (filehandle == INVALID_HANDLE_VALUE)
		WT_ERR_MSG(session, __wt_errno(),
		    "open failed for secondary handle: %s", path);

setupfh:
	WT_ERR(__wt_calloc_one(session, &fh));
	WT_ERR(__wt_strdup(session, name, &fh->name));
	fh->name_hash = hash;
	fh->filehandle = filehandle;
	fh->filehandle_secondary = filehandle_secondary;
	fh->ref = 1;
	fh->direct_io = direct_io;

	/* Set the file's size. */
	if (dio_type != WT_FILE_TYPE_DIRECTORY)
		WT_ERR(__wt_filesize(session, fh, &fh->size));

	/* Configure file extension. */
	if (dio_type == WT_FILE_TYPE_DATA ||
	    dio_type == WT_FILE_TYPE_CHECKPOINT)
		fh->extend_len = conn->data_extend_len;

	/* Configure fallocate/posix_fallocate calls. */
	__wt_fallocate_config(session, fh);

	/*
	 * Repeat the check for a match, but then link onto the database's list
	 * of files.
	 */
	matched = 0;
	__wt_spin_lock(session, &conn->fh_lock);
	SLIST_FOREACH(tfh, &conn->fhhash[bucket], l)
		if (strcmp(name, tfh->name) == 0) {
			++tfh->ref;
			*fhp = tfh;
			matched = 1;
			break;
		}
	if (!matched) {
		WT_CONN_FILE_INSERT(conn, fh, bucket);
		WT_STAT_FAST_CONN_INCR(session, file_open);

		*fhp = fh;
	}
	__wt_spin_unlock(session, &conn->fh_lock);
	if (matched) {
err:		if (fh != NULL) {
			__wt_free(session, fh->name);
			__wt_free(session, fh);
		}
		if (filehandle != INVALID_HANDLE_VALUE)
			(void)CloseHandle(filehandle);
		if (filehandle_secondary != INVALID_HANDLE_VALUE)
			(void)CloseHandle(filehandle_secondary);
	}

	__wt_free(session, path);
	return (ret);
}
コード例 #21
0
ファイル: os_fhandle.c プロジェクト: ralic/mongo
/*
 * __wt_open --
 *	Open a file handle.
 */
int
__wt_open(WT_SESSION_IMPL *session,
          const char *name, uint32_t file_type, uint32_t flags, WT_FH **fhp)
{
    WT_CONNECTION_IMPL *conn;
    WT_DECL_RET;
    WT_FH *fh;
    bool lock_file, open_called;
    char *path;

    WT_ASSERT(session, file_type != 0);	/* A file type is required. */

    conn = S2C(session);
    fh = NULL;
    open_called = false;
    path = NULL;

    WT_RET(__open_verbose(session, name, file_type, flags));

    /* Check if the handle is already open. */
    if (__wt_handle_search(session, name, true, NULL, &fh)) {
        /*
         * XXX
         * The in-memory implementation has to reset the file offset
         * when a file is re-opened (which obviously also depends on
         * in-memory configurations never opening a file in more than
         * one thread at a time). This needs to be fixed.
         */
        if (F_ISSET(fh, WT_FH_IN_MEMORY) && fh->ref == 1)
            fh->off = 0;
        *fhp = fh;
        return (0);
    }

    /* Allocate a structure and set the name. */
    WT_ERR(__wt_calloc_one(session, &fh));
    WT_ERR(__wt_strdup(session, name, &fh->name));

    /*
     * If this is a read-only connection, open all files read-only except
     * the lock file.
     *
     * The only file created in read-only mode is the lock file.
     */
    if (F_ISSET(conn, WT_CONN_READONLY)) {
        lock_file = strcmp(name, WT_SINGLETHREAD) == 0;
        if (!lock_file)
            LF_SET(WT_OPEN_READONLY);
        WT_ASSERT(session, lock_file || !LF_ISSET(WT_OPEN_CREATE));
    }

    /* Create the path to the file. */
    if (!LF_ISSET(WT_OPEN_FIXED))
        WT_ERR(__wt_filename(session, name, &path));

    /* Call the underlying open function. */
    WT_ERR(conn->handle_open(
               session, fh, path == NULL ? name : path, file_type, flags));
    open_called = true;

    /*
     * Repeat the check for a match: if there's no match, link our newly
     * created handle onto the database's list of files.
     */
    if (__wt_handle_search(session, name, true, fh, fhp)) {
err:
        if (open_called)
            WT_TRET(fh->fh_close(session, fh));
        if (fh != NULL) {
            __wt_free(session, fh->name);
            __wt_free(session, fh);
        }
    }

    __wt_free(session, path);
    return (ret);
}
コード例 #22
0
ファイル: os_fhandle.c プロジェクト: Machyne/mongo
/*
 * __wt_open --
 *	Open a file handle.
 */
int
__wt_open(WT_SESSION_IMPL *session,
    const char *name, WT_FS_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp)
{
	WT_CONNECTION_IMPL *conn;
	WT_DECL_RET;
	WT_FH *fh;
	WT_FILE_SYSTEM *file_system;
	bool lock_file, open_called;
	char *path;

	WT_ASSERT(session, file_type != 0);	/* A file type is required. */

	conn = S2C(session);
	file_system = conn->file_system;
	fh = NULL;
	open_called = false;
	path = NULL;

	WT_RET(__open_verbose(session, name, file_type, flags));

	/* Check if the handle is already open. */
	if (__handle_search(session, name, NULL, &fh)) {
		*fhp = fh;
		return (0);
	}

	/* Allocate and initialize the handle. */
	WT_ERR(__wt_calloc_one(session, &fh));
	WT_ERR(__wt_strdup(session, name, &fh->name));

	/*
	 * If this is a read-only connection, open all files read-only except
	 * the lock file.
	 *
	 * The only file created in read-only mode is the lock file.
	 */
	if (F_ISSET(conn, WT_CONN_READONLY)) {
		lock_file = strcmp(name, WT_SINGLETHREAD) == 0;
		if (!lock_file)
			LF_SET(WT_FS_OPEN_READONLY);
		WT_ASSERT(session, lock_file || !LF_ISSET(WT_FS_OPEN_CREATE));
	}

	/* Create the path to the file. */
	if (!LF_ISSET(WT_FS_OPEN_FIXED))
		WT_ERR(__wt_filename(session, name, &path));

	/* Call the underlying open function. */
	WT_ERR(file_system->fs_open_file(file_system, &session->iface,
	    path == NULL ? name : path, file_type, flags, &fh->handle));
	open_called = true;

	WT_ERR(__fhandle_method_finalize(
	    session, fh->handle, LF_ISSET(WT_FS_OPEN_READONLY)));

	/*
	 * Repeat the check for a match: if there's no match, link our newly
	 * created handle onto the database's list of files.
	 */
	if (__handle_search(session, name, fh, fhp)) {
err:		if (open_called)
			WT_TRET(fh->handle->close(
			    fh->handle, (WT_SESSION *)session));
		if (fh != NULL) {
			__wt_free(session, fh->name);
			__wt_free(session, fh);
		}
	}

	__wt_free(session, path);
	return (ret);
}
コード例 #23
0
ファイル: os_dir.c プロジェクト: 3rf/mongo
/*
 * __wt_dirlist --
 *	Get a list of files from a directory, optionally filtered by
 *	a given prefix.
 */
int
__wt_dirlist(WT_SESSION_IMPL *session, const char *dir, const char *prefix,
    uint32_t flags, char ***dirlist, u_int *countp)
{
	struct dirent *dp;
	DIR *dirp;
	WT_DECL_RET;
	size_t dirallocsz;
	u_int count, dirsz;
	int match;
	char **entries, *path;

	*dirlist = NULL;
	*countp = 0;

	WT_RET(__wt_filename(session, dir, &path));

	dirp = NULL;
	dirallocsz = 0;
	dirsz = 0;
	entries = NULL;
	if (flags == 0)
		LF_SET(WT_DIRLIST_INCLUDE);

	WT_ERR(__wt_verbose(session, WT_VERB_FILEOPS,
	    "wt_dirlist of %s %s prefix %s",
	    path, LF_ISSET(WT_DIRLIST_INCLUDE) ? "include" : "exclude",
	    prefix == NULL ? "all" : prefix));

	WT_SYSCALL_RETRY(((dirp = opendir(path)) == NULL ? 1 : 0), ret);
	if (ret != 0)
		WT_ERR_MSG(session, ret, "%s: opendir", path);
	for (dirsz = 0, count = 0; (dp = readdir(dirp)) != NULL;) {
		/*
		 * Skip . and ..
		 */
		if (strcmp(dp->d_name, ".") == 0 ||
		    strcmp(dp->d_name, "..") == 0)
			continue;
		match = 0;
		if (prefix != NULL &&
		    ((LF_ISSET(WT_DIRLIST_INCLUDE) &&
		    WT_PREFIX_MATCH(dp->d_name, prefix)) ||
		    (LF_ISSET(WT_DIRLIST_EXCLUDE) &&
		    !WT_PREFIX_MATCH(dp->d_name, prefix))))
			match = 1;
		if (prefix == NULL || match) {
			/*
			 * We have a file name we want to return.
			 */
			count++;
			if (count > dirsz) {
				dirsz += WT_DIR_ENTRY;
				WT_ERR(__wt_realloc_def(
				    session, &dirallocsz, dirsz, &entries));
			}
			WT_ERR(__wt_strdup(
			    session, dp->d_name, &entries[count-1]));
		}
	}
	if (count > 0)
		*dirlist = entries;
	*countp = count;
err:
	if (dirp != NULL)
		(void)closedir(dirp);
	__wt_free(session, path);

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

	if (*dirlist != NULL) {
		for (count = dirsz; count > 0; count--)
			__wt_free(session, entries[count]);
		__wt_free(session, entries);
	}
	WT_RET_MSG(session, ret, "dirlist %s prefix %s", dir, prefix);
}