コード例 #1
0
ファイル: err.c プロジェクト: DavidAlphaFox/mongodb
/*
 * __handle_error_default --
 *	Default WT_EVENT_HANDLER->handle_error implementation: send to stderr.
 */
static int
__handle_error_default(WT_EVENT_HANDLER *handler,
    WT_SESSION *wt_session, int error, const char *errmsg)
{
	WT_SESSION_IMPL *session;

	WT_UNUSED(handler);
	WT_UNUSED(error);

	session = (WT_SESSION_IMPL *)wt_session;

	WT_RET(__wt_fprintf(session, stderr, "%s\n", errmsg));
	WT_RET(__wt_fflush(session, stderr));
	return (0);
}
コード例 #2
0
ファイル: cur_backup.c プロジェクト: brianleepzx/mongo
/*
 * __backup_list_uri_append --
 *	Append a new file name to the list, allocate space as necessary.
 *	Called via the schema_worker function.
 */
static int
__backup_list_uri_append(
    WT_SESSION_IMPL *session, const char *name, bool *skip)
{
	WT_CURSOR_BACKUP *cb;
	char *value;

	cb = session->bkp_cursor;
	WT_UNUSED(skip);

	/*
	 * While reading the metadata file, check there are no data sources
	 * that can't support hot backup.  This checks for a data source that's
	 * non-standard, which can't be backed up, but is also sanity checking:
	 * if there's an entry backed by anything other than a file or lsm
	 * entry, we're confused.
	 */
	if (WT_PREFIX_MATCH(name, "log:")) {
		WT_RET(__backup_log_append(session, cb, false));
		return (0);
	}

	if (!WT_PREFIX_MATCH(name, "file:") &&
	    !WT_PREFIX_MATCH(name, "colgroup:") &&
	    !WT_PREFIX_MATCH(name, "index:") &&
	    !WT_PREFIX_MATCH(name, "lsm:") &&
	    !WT_PREFIX_MATCH(name, "table:"))
		WT_RET_MSG(session, ENOTSUP,
		    "hot backup is not supported for objects of type %s",
		    name);

	/* Ignore the lookaside table. */
	if (strcmp(name, WT_LAS_URI) == 0)
		return (0);

	/* Add the metadata entry to the backup file. */
	WT_RET(__wt_metadata_search(session, name, &value));
	WT_RET(__wt_fprintf(cb->bfp, "%s\n%s\n", name, value));
	__wt_free(session, value);

	/* Add file type objects to the list of files to be copied. */
	if (WT_PREFIX_MATCH(name, "file:"))
		WT_RET(__backup_list_append(session, cb, name));

	return (0);
}
コード例 #3
0
ファイル: txn_log.c プロジェクト: DINKIN/mongo
/*
 * __txn_printlog --
 *	Print a log record in a human-readable format.
 */
static int
__txn_printlog(WT_SESSION_IMPL *session,
    WT_ITEM *rawrec, WT_LSN *lsnp, WT_LSN *next_lsnp,
    void *cookie, int firstrecord)
{
	WT_LOG_RECORD *logrec;
	WT_TXN_PRINTLOG_ARGS *args;
	const uint8_t *end, *p;
	const char *msg;
	uint64_t txnid;
	uint32_t fileid, lsnfile, lsnoffset, rectype;
	int32_t start;
	bool compressed;

	WT_UNUSED(next_lsnp);
	args = cookie;

	p = WT_LOG_SKIP_HEADER(rawrec->data);
	end = (const uint8_t *)rawrec->data + rawrec->size;
	logrec = (WT_LOG_RECORD *)rawrec->data;
	compressed = F_ISSET(logrec, WT_LOG_RECORD_COMPRESSED);

	/* First, peek at the log record type. */
	WT_RET(__wt_logrec_read(session, &p, end, &rectype));

	if (!firstrecord)
		WT_RET(__wt_fprintf(session, WT_STDOUT(session), ",\n"));

	WT_RET(__wt_fprintf(session, WT_STDOUT(session),
	    "  { \"lsn\" : [%" PRIu32 ",%" PRIu32 "],\n",
	    lsnp->l.file, lsnp->l.offset));
	WT_RET(__wt_fprintf(session, WT_STDOUT(session),
	    "    \"hdr_flags\" : \"%s\",\n", compressed ? "compressed" : ""));
	WT_RET(__wt_fprintf(session, WT_STDOUT(session),
	    "    \"rec_len\" : %" PRIu32 ",\n", logrec->len));
	WT_RET(__wt_fprintf(session, WT_STDOUT(session),
	    "    \"mem_len\" : %" PRIu32 ",\n",
	    compressed ? logrec->mem_len : logrec->len));

	switch (rectype) {
	case WT_LOGREC_CHECKPOINT:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(II), &lsnfile, &lsnoffset));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"type\" : \"checkpoint\",\n"));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"ckpt_lsn\" : [%" PRIu32 ",%" PRIu32 "]\n",
		    lsnfile, lsnoffset));
		break;

	case WT_LOGREC_COMMIT:
		WT_RET(__wt_vunpack_uint(&p, WT_PTRDIFF(end, p), &txnid));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"type\" : \"commit\",\n"));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"txnid\" : %" PRIu64 ",\n", txnid));
		WT_RET(__txn_oplist_printlog(session, &p, end, args->flags));
		break;

	case WT_LOGREC_FILE_SYNC:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(Ii), &fileid, &start));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"type\" : \"file_sync\",\n"));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"fileid\" : %" PRIu32 ",\n", fileid));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"start\" : %" PRId32 "\n", start));
		break;

	case WT_LOGREC_MESSAGE:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(S), &msg));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"type\" : \"message\",\n"));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"message\" : \"%s\"\n", msg));
		break;

	case WT_LOGREC_SYSTEM:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(II), &lsnfile, &lsnoffset));
		WT_RET(__wt_fprintf(session, WT_STDOUT(session),
		    "    \"type\" : \"system\",\n"));
		WT_RET(__txn_oplist_printlog(session, &p, end, args->flags));
		break;
	}

	WT_RET(__wt_fprintf(session, WT_STDOUT(session), "  }"));

	return (0);
}
コード例 #4
0
ファイル: txn_log.c プロジェクト: DINKIN/mongo
		WT_RET(__txn_oplist_printlog(session, &p, end, args->flags));
		break;
	}

	WT_RET(__wt_fprintf(session, WT_STDOUT(session), "  }"));

	return (0);
}

/*
 * __wt_txn_printlog --
 *	Print the log in a human-readable format.
 */
int
__wt_txn_printlog(WT_SESSION *wt_session, uint32_t flags)
    WT_GCC_FUNC_ATTRIBUTE((visibility("default")))
{
	WT_SESSION_IMPL *session;
	WT_TXN_PRINTLOG_ARGS args;

	session = (WT_SESSION_IMPL *)wt_session;
	args.flags = flags;

	WT_RET(__wt_fprintf(session, WT_STDOUT(session), "[\n"));
	WT_RET(__wt_log_scan(
	    session, NULL, WT_LOGSCAN_FIRST, __txn_printlog, &args));
	WT_RET(__wt_fprintf(session, WT_STDOUT(session), "\n]\n"));

	return (0);
}
コード例 #5
0
ファイル: err.c プロジェクト: DavidAlphaFox/mongodb
/*
 * __wt_eventv --
 * 	Report a message to an event handler.
 */
int
__wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
    const char *file_name, int line_number, const char *fmt, va_list ap)
{
	WT_EVENT_HANDLER *handler;
	WT_DECL_RET;
	WT_SESSION *wt_session;
	struct timespec ts;
	size_t len, remain, wlen;
	int prefix_cnt;
	const char *err, *prefix;
	char *end, *p, tid[128];

	/*
	 * We're using a stack buffer because we want error messages no matter
	 * what, and allocating a WT_ITEM, or the memory it needs, might fail.
	 *
	 * !!!
	 * SECURITY:
	 * Buffer placed at the end of the stack in case snprintf overflows.
	 */
	char s[2048];

	/*
	 * !!!
	 * This function MUST handle a NULL WT_SESSION_IMPL handle.
	 *
	 * Without a session, we don't have event handlers or prefixes for the
	 * error message.  Write the error to stderr and call it a day.  (It's
	 * almost impossible for that to happen given how early we allocate the
	 * first session, but if the allocation of the first session fails, for
	 * example, we can end up here without a session.)
	 */
	if (session == NULL) {
		WT_RET(__wt_fprintf(session, stderr,
		    "WiredTiger Error%s%s: ",
		    error == 0 ? "" : ": ",
		    error == 0 ? "" : __wt_strerror(session, error, NULL, 0)));
		WT_RET(__wt_vfprintf(session, stderr, fmt, ap));
		WT_RET(__wt_fprintf(session, stderr, "\n"));
		return (__wt_fflush(session, stderr));
	}

	p = s;
	end = s + sizeof(s);

	/*
	 * We have several prefixes for the error message:
	 * a timestamp and the process and thread ids, the database error
	 * prefix, the data-source's name, and the session's name.  Write them
	 * as a comma-separate list, followed by a colon.
	 */
	prefix_cnt = 0;
	if (__wt_epoch(session, &ts) == 0) {
		__wt_thread_id(tid, sizeof(tid));
		remain = WT_PTRDIFF(end, p);
		wlen = (size_t)snprintf(p, remain,
		    "[%" PRIuMAX ":%" PRIuMAX "][%s]",
		    (uintmax_t)ts.tv_sec, (uintmax_t)ts.tv_nsec / 1000, tid);
		p = wlen >= remain ? end : p + wlen;
		prefix_cnt = 1;
	}
	if ((prefix = S2C(session)->error_prefix) != NULL) {
		remain = WT_PTRDIFF(end, p);
		wlen = (size_t)snprintf(p, remain,
		    "%s%s", prefix_cnt == 0 ? "" : ", ", prefix);
		p = wlen >= remain ? end : p + wlen;
		prefix_cnt = 1;
	}
	prefix = session->dhandle == NULL ? NULL : session->dhandle->name;
	if (prefix != NULL) {
		remain = WT_PTRDIFF(end, p);
		wlen = (size_t)snprintf(p, remain,
		    "%s%s", prefix_cnt == 0 ? "" : ", ", prefix);
		p = wlen >= remain ? end : p + wlen;
		prefix_cnt = 1;
	}
	if ((prefix = session->name) != NULL) {
		remain = WT_PTRDIFF(end, p);
		wlen = (size_t)snprintf(p, remain,
		    "%s%s", prefix_cnt == 0 ? "" : ", ", prefix);
		p = wlen >= remain ? end : p + wlen;
		prefix_cnt = 1;
	}
	if (prefix_cnt != 0) {
		remain = WT_PTRDIFF(end, p);
		wlen = (size_t)snprintf(p, remain, ": ");
		p = wlen >= remain ? end : p + wlen;
	}

	if (file_name != NULL) {
		remain = WT_PTRDIFF(end, p);
		wlen = (size_t)
		    snprintf(p, remain, "%s, %d: ", file_name, line_number);
		p = wlen >= remain ? end : p + wlen;
	}

	remain = WT_PTRDIFF(end, p);
	wlen = (size_t)vsnprintf(p, remain, fmt, ap);
	p = wlen >= remain ? end : p + wlen;

	if (error != 0) {
		/*
		 * When the engine calls __wt_err on error, it often outputs an
		 * error message including the string associated with the error
		 * it's returning.  We could change the calls to call __wt_errx,
		 * but it's simpler to not append an error string if all we are
		 * doing is duplicating an existing error string.
		 *
		 * Use strcmp to compare: both strings are nul-terminated, and
		 * we don't want to run past the end of the buffer.
		 */
		err = __wt_strerror(session, error, NULL, 0);
		len = strlen(err);
		if (WT_PTRDIFF(p, s) < len || strcmp(p - len, err) != 0) {
			remain = WT_PTRDIFF(end, p);
			(void)snprintf(p, remain, ": %s", err);
		}
	}

	/*
	 * If a handler fails, return the error status: if we're in the process
	 * of handling an error, any return value we provide will be ignored by
	 * our caller, our caller presumably already has an error value it will
	 * be returning.
	 *
	 * If an application-specified or default informational message handler
	 * fails, complain using the application-specified or default error
	 * handler.
	 *
	 * If an application-specified error message handler fails, complain
	 * using the default error handler.  If the default error handler fails,
	 * there's nothing to do.
	 */
	wt_session = (WT_SESSION *)session;
	handler = session->event_handler;
	if (msg_event) {
		ret = handler->handle_message(handler, wt_session, s);
		if (ret != 0)
			__handler_failure(session, ret, "message", false);
	} else {
		ret = handler->handle_error(handler, wt_session, error, s);
		if (ret != 0 && handler->handle_error != __handle_error_default)
			__handler_failure(session, ret, "error", true);
	}

	return (ret);
}
コード例 #6
0
ファイル: mutex.c プロジェクト: 7segments/mongo-1
/*
 * __wt_statlog_dump_spinlock --
 *	Log the spin-lock statistics.
 */
int
__wt_statlog_dump_spinlock(WT_CONNECTION_IMPL *conn, const char *tag)
{
	WT_SPINLOCK *spin;
	WT_CONNECTION_STATS_SPINLOCK *p, *t;
	uint64_t block_manager, btree_page, ignore;
	u_int i, j;

	/*
	 * Ignore rare acquisition of a spinlock using a base value of 10 per
	 * second so we don't create graphs we don't care about.
	 */
	ignore = (uint64_t)(conn->stat_usecs / 1000000) * 10;

	/* Output the number of times each spinlock was acquired. */
	block_manager = btree_page = 0;
	for (i = 0; i < WT_ELEMENTS(conn->spinlock_list); ++i) {
		if ((spin = conn->spinlock_list[i]) == NULL)
			continue;

		/*
		 * There are two sets of spinlocks we aggregate, the btree page
		 * locks and the block manager per-file locks.  The reason is
		 * the block manager locks grow with the number of files open
		 * (and LSM and bloom filters can open a lot of files), and
		 * there are 16 btree page locks and splitting them out has not
		 * historically been that informative.
		 */
		if (strcmp(spin->name, "block manager") == 0) {
			block_manager += spin->counter;
			if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_CLEAR))
				spin->counter = 0;
			continue;
		}
		if (strcmp(spin->name, "btree page") == 0) {
			btree_page += spin->counter;
			if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_CLEAR))
				spin->counter = 0;
			continue;
		}

		WT_RET(__wt_fprintf(session, conn->stat_fp,
		    "%s %" PRIu64 " %s spinlock %s: acquisitions\n",
		    conn->stat_stamp,
		    spin->counter <= ignore ? 0 : spin->counter,
		    tag, spin->name));
		if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_CLEAR))
			spin->counter = 0;
	}
	WT_RET(__wt_fprintf(session, conn->stat_fp,
	    "%s %" PRIu64 " %s spinlock %s: acquisitions\n",
	    conn->stat_stamp,
	    block_manager <= ignore ? 0 : block_manager,
	    tag, "block manager"));
	WT_RET(__wt_fprintf(session, conn->stat_fp,
	    "%s %" PRIu64 " %s spinlock %s: acquisitions\n",
	    conn->stat_stamp,
	    btree_page <= ignore ? 0 : btree_page,
	    tag, "btree page"));

	/*
	 * Output the number of times each location acquires its spinlock and
	 * the blocking matrix.
	 */
	for (i = 0; i < WT_ELEMENTS(conn->spinlock_block); ++i) {
		p = &conn->spinlock_block[i];
		if (p->name == NULL)
			continue;

		WT_RET(__wt_fprintf(session, conn->stat_fp,
		    "%s %d %s spinlock %s acquired by %s(%d)\n",
		    conn->stat_stamp,
		    p->total <= ignore ? 0 : p->total,
		    tag,
		    p->name, p->file, p->line));
		if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_CLEAR))
			p->total = 0;

		for (j = 0; j < WT_ELEMENTS(conn->spinlock_block); ++j) {
			t = &conn->spinlock_block[j];
			if (t->name == NULL)
				continue;

			WT_RET(__wt_fprintf(session, conn->stat_fp,
			    "%s %d %s spinlock %s: %s(%d) blocked by %s(%d)\n",
			    conn->stat_stamp,
			    p->blocked[j] <= ignore ? 0 : p->blocked[j],
			    tag,
			    p->name, p->file, p->line,
			    t->file, t->line));
			if (FLD_ISSET(conn->stat_flags, WT_CONN_STAT_CLEAR))
				p->blocked[j] = 0;
		}
	}

	WT_FULL_BARRIER();			/* Minimize the window. */
	return (0);
}