Esempio n. 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);
}
Esempio n. 2
0
File: os_fs.c Progetto: GYGit/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_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);
}
Esempio n. 3
0
/*
 * __wt_hazard_close --
 *	Verify that no hazard pointers are set.
 */
void
__wt_hazard_close(WT_SESSION_IMPL *session)
{
	WT_HAZARD *hp;
	bool found;

	/*
	 * Check for a set hazard pointer and complain if we find one.  We could
	 * just check the session's hazard pointer count, but this is a useful
	 * diagnostic.
	 */
	for (found = false, hp = session->hazard;
	    hp < session->hazard + session->hazard_size; ++hp)
		if (hp->page != NULL) {
			found = true;
			break;
		}
	if (session->nhazard == 0 && !found)
		return;

	__wt_errx(session,
	    "session %p: close hazard pointer table: table not empty",
	    (void *)session);

#ifdef HAVE_DIAGNOSTIC
	__hazard_dump(session);
#endif

	/*
	 * Clear any hazard pointers because it's not a correctness problem
	 * (any hazard pointer we find can't be real because the session is
	 * being closed when we're called). We do this work because session
	 * close isn't that common that it's an expensive check, and we don't
	 * want to let a hazard pointer lie around, keeping a page from being
	 * evicted.
	 *
	 * We don't panic: this shouldn't be a correctness issue (at least, I
	 * can't think of a reason it would be).
	 */
	for (hp = session->hazard;
	    hp < session->hazard + session->hazard_size; ++hp)
		if (hp->page != NULL) {
			hp->page = NULL;
			--session->nhazard;
		}

	if (session->nhazard != 0)
		__wt_errx(session,
		    "session %p: close hazard pointer table: count didn't "
		    "match entries",
		    (void *)session);
}
Esempio n. 4
0
/*
 * __wt_cache_destroy --
 *	Discard the underlying cache.
 */
int
__wt_cache_destroy(WT_SESSION_IMPL *session)
{
	WT_CACHE *cache;
	WT_CONNECTION_IMPL *conn;
	WT_DECL_RET;
	WT_SESSION *wt_session;
	int i;

	conn = S2C(session);
	cache = conn->cache;

	if (cache == NULL)
		return (0);

	/* The cache should be empty at this point.  Complain if not. */
	if (cache->pages_inmem != cache->pages_evict)
		__wt_errx(session,
		    "cache server: exiting with %" PRIu64 " pages in "
		    "memory and %" PRIu64 " pages evicted",
		    cache->pages_inmem, cache->pages_evict);
	if (cache->bytes_inmem != 0)
		__wt_errx(session,
		    "cache server: exiting with %" PRIu64 " bytes in memory",
		    cache->bytes_inmem);
	if (cache->bytes_dirty_intl + cache->bytes_dirty_leaf != 0 ||
	    cache->pages_dirty_intl + cache->pages_dirty_leaf != 0)
		__wt_errx(session,
		    "cache server: exiting with %" PRIu64
		    " bytes dirty and %" PRIu64 " pages dirty",
		    cache->bytes_dirty_intl + cache->bytes_dirty_leaf,
		    cache->pages_dirty_intl + cache->pages_dirty_leaf);

	WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond));
	__wt_spin_destroy(session, &cache->evict_pass_lock);
	__wt_spin_destroy(session, &cache->evict_queue_lock);
	__wt_spin_destroy(session, &cache->evict_walk_lock);
	wt_session = &cache->walk_session->iface;
	if (wt_session != NULL)
		WT_TRET(wt_session->close(wt_session, NULL));

	for (i = 0; i < WT_EVICT_QUEUE_MAX; ++i) {
		__wt_spin_destroy(session, &cache->evict_queues[i].evict_lock);
		__wt_free(session, cache->evict_queues[i].evict_queue);
	}

	__wt_free(session, conn->cache);
	return (ret);
}
Esempio n. 5
0
/*
 * __session_commit_transaction --
 *	WT_SESSION->commit_transaction method.
 */
static int
__session_commit_transaction(WT_SESSION *wt_session, const char *config)
{
	WT_DECL_RET;
	WT_SESSION_IMPL *session;
	WT_TXN *txn;

	session = (WT_SESSION_IMPL *)wt_session;
	SESSION_API_CALL(session, commit_transaction, config, cfg);
	WT_CSTAT_INCR(session, txn_commit);

	txn = &session->txn;
	if (F_ISSET(txn, TXN_ERROR)) {
		__wt_errx(session, "failed transaction requires rollback");
		ret = EINVAL;
	}

	WT_TRET(__session_reset_cursors(session));

	if (ret == 0)
		ret = __wt_txn_commit(session, cfg);
	else
		(void)__wt_txn_rollback(session, cfg);

err:	API_END(session);
	return (ret);
}
Esempio n. 6
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_RET;
	WT_DECL_ITEM(name_wide);
	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();
		__wt_errx(session,
		    "%s: file-remove: DeleteFileW: %s",
		    name, __wt_formatmessage(session, windows_error));
		WT_ERR(__wt_map_windows_error(windows_error));
	}

err:	__wt_scr_free(session, &name_wide);
	return (ret);
}
Esempio n. 7
0
/*
 * __win_file_sync --
 *	MSVC fsync.
 */
static int
__win_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
{
	DWORD windows_error;
	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();
		__wt_errx(session,
		    "%s handle-sync: FlushFileBuffers: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}
	return (0);
}
Esempio n. 8
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;
	WT_DECL_RET;
	WIN32_FILE_ATTRIBUTE_DATA data;
	WT_DECL_ITEM(name_wide);
	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();
		__wt_errx(session,
		    "%s: file-size: GetFileAttributesEx: %s",
		    name, __wt_formatmessage(session, windows_error));
		WT_ERR(__wt_map_windows_error(windows_error));
	}

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

err:	__wt_scr_free(session, &name_wide);
	return (ret);
}
Esempio n. 9
0
/*
 * __wt_close_connection_close --
 *	Close any open file handles at connection close.
 */
int
__wt_close_connection_close(WT_SESSION_IMPL *session)
{
    WT_DECL_RET;
    WT_FH *fh;
    WT_CONNECTION_IMPL *conn;

    conn = S2C(session);

    while ((fh = TAILQ_FIRST(&conn->fhqh)) != NULL) {
        /*
         * In-memory configurations will have open files, but the ref
         * counts should be zero.
         */
        if (!F_ISSET(conn, WT_CONN_IN_MEMORY) || fh->ref != 0) {
            ret = EBUSY;
            __wt_errx(session,
                      "Connection has open file handles: %s", fh->name);
        }

        fh->ref = 1;
        F_CLR(fh, WT_FH_IN_MEMORY);

        WT_TRET(__wt_close(session, &fh));
    }
    return (ret);
}
Esempio n. 10
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);
}
Esempio n. 11
0
/*
 * __wt_page_out --
 *	Discard an in-memory page, freeing all memory associated with it.
 */
void
__wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep)
{
	WT_PAGE *page;

	/*
	 * When a page is discarded, it's been disconnected from its parent and
	 * its parent's WT_REF structure may now point to a different page.
	 * Make sure we don't accidentally use the page itself or any other
	 * information.
	 */
	page = *pagep;
	*pagep = NULL;
	page->parent = NULL;
	page->ref = NULL;

	WT_ASSERT(session, !F_ISSET_ATOMIC(page, WT_PAGE_EVICT_LRU));

#ifdef HAVE_DIAGNOSTIC
	{
	WT_HAZARD *hp;
	if ((hp = __wt_page_hazard_check(session, page)) != NULL)
		__wt_errx(session,
		    "discarded page has hazard pointer: (%p: %s, line %d)",
		    hp->page, hp->file, hp->line);
	}
#endif
	/* Update the cache's information. */
	__wt_cache_page_evict(session, page);

	/* Free the page modification information. */
	if (page->modify != NULL)
		__free_page_modify(session, page);

	switch (page->type) {
	case WT_PAGE_COL_FIX:
		break;
	case WT_PAGE_COL_INT:
		__free_page_col_int(session, page);
		break;
	case WT_PAGE_COL_VAR:
		__free_page_col_var(session, page);
		break;
	case WT_PAGE_ROW_INT:
		__free_page_row_int(session, page);
		break;
	case WT_PAGE_ROW_LEAF:
		__free_page_row_leaf(session, page);
		break;
	}

	/* Free any allocated disk image. */
	if (!F_ISSET_ATOMIC(page, WT_PAGE_DISK_NOT_ALLOC))
		__wt_free(session, page->dsk);

	__wt_overwrite_and_free(session, page);
}
Esempio n. 12
0
 /*
 * __wt_curindex_joined --
 *	Produce an error that this cursor is being used in a join call.
 */
int
__wt_curindex_joined(WT_CURSOR *cursor)
{
	WT_SESSION_IMPL *session;

	session = (WT_SESSION_IMPL *)cursor->session;
	__wt_errx(session, "index cursor is being used in a join");
	return (ENOTSUP);
}
Esempio n. 13
0
/*
 * __wt_block_read_off --
 *	Read an addr/size pair referenced block into a buffer.
 */
int
__wt_block_read_off(WT_SESSION_IMPL *session, WT_BLOCK *block,
    WT_ITEM *buf, wt_off_t offset, uint32_t size, uint32_t cksum)
{
	WT_BLOCK_HEADER *blk;
	size_t bufsize;
	uint32_t page_cksum;

	WT_RET(__wt_verbose(session, WT_VERB_READ,
	    "off %" PRIuMAX ", size %" PRIu32 ", cksum %" PRIu32,
	    (uintmax_t)offset, size, cksum));

	WT_STAT_FAST_CONN_INCR(session, block_read);
	WT_STAT_FAST_CONN_INCRV(session, block_byte_read, size);

	/*
	 * Grow the buffer as necessary and read the block.  Buffers should be
	 * aligned for reading, but there are lots of buffers (for example, file
	 * cursors have two buffers each, key and value), and it's difficult to
	 * be sure we've found all of them.  If the buffer isn't aligned, it's
	 * an easy fix: set the flag and guarantee we reallocate it.  (Most of
	 * the time on reads, the buffer memory has not yet been allocated, so
	 * we're not adding any additional processing time.)
	 */
	if (F_ISSET(buf, WT_ITEM_ALIGNED))
		bufsize = size;
	else {
		F_SET(buf, WT_ITEM_ALIGNED);
		bufsize = WT_MAX(size, buf->memsize + 10);
	}
	WT_RET(__wt_buf_init(session, buf, bufsize));
	WT_RET(__wt_read(session, block->fh, offset, size, buf->mem));
	buf->size = size;

	blk = WT_BLOCK_HEADER_REF(buf->mem);
	page_cksum = blk->cksum;
	if (page_cksum == cksum) {
		blk->cksum = 0;
		page_cksum = __wt_cksum(buf->mem,
		    F_ISSET(blk, WT_BLOCK_DATA_CKSUM) ?
		    size : WT_BLOCK_COMPRESS_SKIP);
		if (page_cksum == cksum)
			return (0);
	}

	if (!F_ISSET(session, WT_SESSION_SALVAGE_CORRUPT_OK))
		__wt_errx(session,
		    "read checksum error [%" PRIu32 "B @ %" PRIuMAX ", %"
		    PRIu32 " != %" PRIu32 "]",
		    size, (uintmax_t)offset, cksum, page_cksum);

	/* Panic if a checksum fails during an ordinary read. */
	return (block->verify ||
	    F_ISSET(session, WT_SESSION_SALVAGE_CORRUPT_OK) ?
	    WT_ERROR : __wt_illegal_value(session, block->name));
}
Esempio n. 14
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();
		__wt_errx(session,
		    "%s: handle-close: CloseHandle: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
		ret = __wt_map_windows_error(windows_error);
	}

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

	__wt_free(session, file_handle->name);
	__wt_free(session, win_fh);
	return (ret);
}
Esempio n. 15
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);
}
Esempio n. 16
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_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();
			__wt_errx(session,
			    "%s: handle-lock: LockFile: %s",
			    file_handle->name,
			    __wt_formatmessage(session, windows_error));
			return (__wt_map_windows_error(windows_error));
		}
	} else
		if (UnlockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) {
			windows_error = __wt_getlasterror();
			__wt_errx(session,
			    "%s: handle-lock: UnlockFile: %s",
			    file_handle->name,
			    __wt_formatmessage(session, windows_error));
			return (__wt_map_windows_error(windows_error));
		}
	return (0);
}
Esempio n. 17
0
/*
 * __hazard_dump --
 *	Display the list of hazard pointers.
 */
static void
__hazard_dump(WT_SESSION_IMPL *session)
{
    WT_HAZARD *hp;

    for (hp = session->hazard;
            hp < session->hazard + session->hazard_size; ++hp)
        if (hp->page != NULL)
            __wt_errx(session,
                      "session %p: hazard pointer %p: %s, line %d",
                      session, hp->page, hp->file, hp->line);
}
Esempio n. 18
0
/*
 * __wt_cache_destroy --
 *	Discard the underlying cache.
 */
int
__wt_cache_destroy(WT_SESSION_IMPL *session)
{
	WT_CACHE *cache;
	WT_CONNECTION_IMPL *conn;
	WT_DECL_RET;

	conn = S2C(session);
	cache = conn->cache;

	if (cache == NULL)
		return (0);

	/* The cache should be empty at this point.  Complain if not. */
	if (cache->pages_inmem != cache->pages_evict)
		__wt_errx(session,
		    "cache server: exiting with %" PRIu64 " pages in "
		    "memory and %" PRIu64 " pages evicted",
		    cache->pages_inmem, cache->pages_evict);
	if (cache->bytes_inmem != 0)
		__wt_errx(session,
		    "cache server: exiting with %" PRIu64 " bytes in memory",
		    cache->bytes_inmem);
	if (cache->bytes_dirty != 0 || cache->pages_dirty != 0)
		__wt_errx(session,
		    "cache server: exiting with %" PRIu64
		    " bytes dirty and %" PRIu64 " pages dirty",
		    cache->bytes_dirty, cache->pages_dirty);

	WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond));
	WT_TRET(__wt_cond_destroy(session, &cache->evict_waiter_cond));
	__wt_spin_destroy(session, &cache->evict_lock);
	__wt_spin_destroy(session, &cache->evict_walk_lock);

	__wt_free(session, cache->evict_queue);
	__wt_free(session, conn->cache);
	return (ret);
}
Esempio n. 19
0
/*
 * __wt_attach --
 *	A routine to wait for the debugging to attach.
 */
void
__wt_attach(WT_SESSION_IMPL *session)
{
#ifdef HAVE_ATTACH
	__wt_errx(session, "process ID %" PRIdMAX
	    ": waiting for debugger...", (intmax_t)getpid());

	/* Sleep forever, the debugger will interrupt us when it attaches. */
	for (;;)
		__wt_sleep(100, 0);
#else
	WT_UNUSED(session);
#endif
}
Esempio n. 20
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);
}
Esempio n. 21
0
/*
 * __wt_meta_track_on --
 *	Turn on metadata operation tracking.
 */
int
__wt_meta_track_on(WT_SESSION_IMPL *session)
{
	if (session->meta_track_nest++ == 0) {
		if (!F_ISSET(&session->txn, WT_TXN_RUNNING)) {
#ifdef WT_ENABLE_SCHEMA_TXN
			WT_RET(__wt_txn_begin(session, NULL));
			__wt_errx(session, "TRACK: Using internal schema txn");
#endif
			F_SET(session, WT_SESSION_SCHEMA_TXN);
		}
		WT_RET(__meta_track_next(session, NULL));
	}

	return (0);
}
Esempio n. 22
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);
}
Esempio n. 23
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);
}
Esempio n. 24
0
File: os_fs.c Progetto: GYGit/mongo
/*
 * __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);
}
Esempio n. 25
0
/*
 * __wt_close_connection_close --
 *	Close any open file handles at connection close.
 */
int
__wt_close_connection_close(WT_SESSION_IMPL *session)
{
	WT_DECL_RET;
	WT_FH *fh;
	WT_CONNECTION_IMPL *conn;

	conn = S2C(session);

	while ((fh = TAILQ_FIRST(&conn->fhqh)) != NULL) {
		if (fh->ref != 0) {
			ret = EBUSY;
			__wt_errx(session,
			    "Connection has open file handles: %s", fh->name);
		}

		fh->ref = 1;

		WT_TRET(__wt_close(session, &fh));
	}
	return (ret);
}
Esempio n. 26
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);
}
Esempio n. 27
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));
}
Esempio n. 28
0
/*
 * __log_slot_dump --
 *	Dump the entire slot state.
 */
static void
__log_slot_dump(WT_SESSION_IMPL *session)
{
	WT_CONNECTION_IMPL *conn;
	WT_LOG *log;
	WT_LOGSLOT *slot;
	int earliest, i;

	conn = S2C(session);
	log = conn->log;
	earliest = 0;
	for (i = 0; i < WT_SLOT_POOL; i++) {
		slot = &log->slot_pool[i];
		if (__wt_log_cmp(&slot->slot_release_lsn,
		    &log->slot_pool[earliest].slot_release_lsn) < 0)
			earliest = i;
		__wt_errx(session, "Slot %d:", i);
		__wt_errx(session, "    State: %" PRIx64 " Flags: %" PRIx32,
		    (uint64_t)slot->slot_state, slot->flags);
		__wt_errx(session, "    Start LSN: %" PRIu32 "/%" PRIu32,
		    slot->slot_start_lsn.l.file, slot->slot_start_lsn.l.offset);
		__wt_errx(session, "    End  LSN: %" PRIu32 "/%" PRIu32,
		    slot->slot_end_lsn.l.file, slot->slot_end_lsn.l.offset);
		__wt_errx(session, "    Release LSN: %" PRIu32 "/%" PRIu32,
		    slot->slot_release_lsn.l.file,
		    slot->slot_release_lsn.l.offset);
		__wt_errx(session, "    Offset: start: %" PRIuMAX
		    " last:%" PRIuMAX, (uintmax_t)slot->slot_start_offset,
		    (uintmax_t)slot->slot_last_offset);
		__wt_errx(session, "    Unbuffered: %" PRId64
		    " error: %" PRId32, slot->slot_unbuffered,
		    slot->slot_error);
	}
	__wt_errx(session, "Earliest slot: %d", earliest);

}
Esempio n. 29
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;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;
	LARGE_INTEGER size;

	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();
	__wt_errx(session,
	    "%s: handle-size: GetFileSizeEx: %s",
	    file_handle->name, __wt_formatmessage(session, windows_error));
	return (__wt_map_windows_error(windows_error));
}
Esempio n. 30
-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;
	WT_FILE_HANDLE_WIN *win_fh;
	WT_SESSION_IMPL *session;
	LARGE_INTEGER largeint;

	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();
		__wt_errx(session,
		    "%s: handle-set-end: SetFilePointerEx: %s",
		    file_handle->name,
		    __wt_formatmessage(session, windows_error));
		return (__wt_map_windows_error(windows_error));
	}

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