Exemplo n.º 1
0
/*
 * __block_buffer_to_addr --
 *	Convert a filesystem address cookie into its components, UPDATING the
 * caller's buffer reference so it can be called repeatedly to load a buffer.
 */
static int
__block_buffer_to_addr(uint32_t allocsize,
    const uint8_t **pp, wt_off_t *offsetp, uint32_t *sizep, uint32_t *checksump)
{
	uint64_t o, s, c;

	WT_RET(__wt_vunpack_uint(pp, 0, &o));
	WT_RET(__wt_vunpack_uint(pp, 0, &s));
	WT_RET(__wt_vunpack_uint(pp, 0, &c));

	/*
	 * To avoid storing large offsets, we minimize the value by subtracting
	 * a block for description information, then storing a count of block
	 * allocation units.  That implies there is no such thing as an
	 * "invalid" offset though, they could all be valid (other than very
	 * large numbers), which is what we didn't want to store in the first
	 * place.  Use the size: writing a block of size 0 makes no sense, so
	 * that's the out-of-band value.  Once we're out of this function and
	 * are working with a real file offset, size and checksum triplet, there
	 * can be invalid offsets, that's simpler than testing sizes of 0 all
	 * over the place.
	 */
	if (s == 0) {
		*offsetp = 0;
		*sizep = *checksump = 0;
	} else {
		*offsetp = (wt_off_t)(o + 1) * allocsize;
		*sizep = (uint32_t)s * allocsize;
		*checksump = (uint32_t)c;
	}
	return (0);
}
Exemplo n.º 2
0
/*
 * __block_buffer_to_ckpt --
 *	Convert a checkpoint cookie into its components.
 */
static int
__block_buffer_to_ckpt(WT_SESSION_IMPL *session,
    uint32_t allocsize, const uint8_t *p, WT_BLOCK_CKPT *ci)
{
	uint64_t a;
	const uint8_t **pp;

	ci->version = *p++;
	if (ci->version != WT_BM_CHECKPOINT_VERSION)
		WT_RET_MSG(session, WT_ERROR, "unsupported checkpoint version");

	pp = &p;
	WT_RET(__block_buffer_to_addr(allocsize, pp,
	    &ci->root_offset, &ci->root_size, &ci->root_checksum));
	WT_RET(__block_buffer_to_addr(allocsize, pp,
	    &ci->alloc.offset, &ci->alloc.size, &ci->alloc.checksum));
	WT_RET(__block_buffer_to_addr(allocsize, pp,
	    &ci->avail.offset, &ci->avail.size, &ci->avail.checksum));
	WT_RET(__block_buffer_to_addr(allocsize, pp,
	    &ci->discard.offset, &ci->discard.size, &ci->discard.checksum));
	WT_RET(__wt_vunpack_uint(pp, 0, &a));
	ci->file_size = (wt_off_t)a;
	WT_RET(__wt_vunpack_uint(pp, 0, &a));
	ci->ckpt_size = a;

	return (0);
}
Exemplo n.º 3
0
/*
 * __txn_log_recover --
 *	Roll the log forward to recover committed changes.
 */
static int
__txn_log_recover(WT_SESSION_IMPL *session,
    WT_ITEM *logrec, WT_LSN *lsnp, WT_LSN *next_lsnp,
    void *cookie, int firstrecord)
{
	WT_RECOVERY *r;
	const uint8_t *end, *p;
	uint64_t txnid;
	uint32_t rectype;

	WT_UNUSED(next_lsnp);
	r = cookie;
	p = WT_LOG_SKIP_HEADER(logrec->data);
	end = (const uint8_t *)logrec->data + logrec->size;
	WT_UNUSED(firstrecord);

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

	switch (rectype) {
	case WT_LOGREC_CHECKPOINT:
		if (r->metadata_only)
			WT_RET(__wt_txn_checkpoint_logread(
			    session, &p, end, &r->ckpt_lsn));
		break;

	case WT_LOGREC_COMMIT:
		WT_RET(__wt_vunpack_uint(&p, WT_PTRDIFF(end, p), &txnid));
		WT_UNUSED(txnid);
		WT_RET(__txn_commit_apply(r, lsnp, &p, end));
		break;
	}

	return (0);
}
Exemplo n.º 4
0
void
test_value(int64_t val)
{
	const uint8_t *cp;
	uint8_t buf[10], *p;
	int64_t sinput, soutput;
	uint64_t uinput, uoutput;
	size_t used_len;

	sinput = val;
	p = buf;
	assert(__wt_vpack_int(&p, sizeof(buf), sinput) == 0);
	used_len = (size_t)(p - buf);
	cp = buf;
	assert(__wt_vunpack_int(&cp, used_len, &soutput) == 0);
	/* Ensure we got the correct value back */
	if (sinput != soutput) {
		fprintf(stderr, "mismatch %" PRIu64 ", %" PRIu64 "\n",
		    sinput, soutput);
		abort();
	}
	/* Ensure that decoding used the correct amount of buffer */
	if (cp != p) {
		fprintf(stderr,
		    "Unpack consumed wrong size for %" PRId64
		    ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n",
		    sinput, used_len, cp > p ?
		    used_len + (size_t)(cp - p) : /* More than buf used */
		    used_len - (size_t)(p - cp)); /* Less than buf used */
		abort();
	}

	/* Test unsigned, convert negative into bigger positive values */
	uinput = (uint64_t)val;

	p = buf;
	assert(__wt_vpack_uint(&p, sizeof(buf), uinput) == 0);
	cp = buf;
	assert(__wt_vunpack_uint(
	    &cp, sizeof(buf), &uoutput) == 0);
	/* Ensure we got the correct value back */
	if (sinput != soutput) {
		fprintf(stderr, "mismatch %" PRIu64 ", %" PRIu64 "\n",
		    sinput, soutput);
		abort();
	}
	/* Ensure that decoding used the correct amount of buffer */
	if (cp != p) {
		fprintf(stderr,
		    "Unpack consumed wrong size for %" PRId64
		    ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n",
		    sinput, used_len, cp > p ?
		    used_len + (size_t)(cp - p) :
		    used_len - (size_t)(p - cp));
		abort();
	}
}
Exemplo n.º 5
0
int
__wt_logrec_read(WT_SESSION_IMPL *session,
    const uint8_t **pp, const uint8_t *end, uint32_t *rectypep)
{
	uint64_t rectype;

	WT_UNUSED(session);
	WT_RET(__wt_vunpack_uint(pp, WT_PTRDIFF(end, *pp), &rectype));
	*rectypep = (uint32_t)rectype;
	return (0);
}
Exemplo n.º 6
0
/*
 * __curjoin_split_key --
 *	Copy the primary key from a cursor (either main table or index)
 *	to another cursor.  When copying from an index file, the index
 *	key is also returned.
 *
 */
static int
__curjoin_split_key(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
    WT_ITEM *idxkey, WT_CURSOR *tocur, WT_CURSOR *fromcur,
    const char *repack_fmt, bool isindex)
{
	WT_CURSOR *firstcg_cur;
	WT_CURSOR_INDEX *cindex;
	WT_ITEM *keyp;
	const uint8_t *p;

	if (isindex) {
		cindex = ((WT_CURSOR_INDEX *)fromcur);
		/*
		 * Repack tells us where the index key ends; advance past
		 * that to get where the raw primary key starts.
		 */
		WT_RET(__wt_struct_repack(session, cindex->child->key_format,
		    repack_fmt != NULL ? repack_fmt : cindex->iface.key_format,
		    &cindex->child->key, idxkey));
		WT_ASSERT(session, cindex->child->key.size > idxkey->size);
		tocur->key.data = (uint8_t *)idxkey->data + idxkey->size;
		tocur->key.size = cindex->child->key.size - idxkey->size;
		if (WT_CURSOR_RECNO(tocur)) {
			p = (const uint8_t *)tocur->key.data;
			WT_RET(__wt_vunpack_uint(&p, tocur->key.size,
			    &tocur->recno));
		} else
			tocur->recno = 0;
	} else {
		firstcg_cur = ((WT_CURSOR_TABLE *)fromcur)->cg_cursors[0];
		keyp = &firstcg_cur->key;
		if (WT_CURSOR_RECNO(tocur)) {
			WT_ASSERT(session, keyp->size == sizeof(uint64_t));
			tocur->recno = *(uint64_t *)keyp->data;
			WT_RET(__curjoin_pack_recno(session, tocur->recno,
			    cjoin->recno_buf, sizeof(cjoin->recno_buf),
			    &tocur->key));
		} else {
			WT_ITEM_SET(tocur->key, *keyp);
			tocur->recno = 0;
		}
		idxkey->data = NULL;
		idxkey->size = 0;
	}
	return (0);
}
Exemplo n.º 7
0
/*
 * __txn_log_recover --
 *	Roll the log forward to recover committed changes.
 */
static int
__txn_log_recover(WT_SESSION_IMPL *session,
    WT_ITEM *logrec, WT_LSN *lsnp, WT_LSN *next_lsnp,
    void *cookie, int firstrecord)
{
	WT_DECL_RET;
	WT_RECOVERY *r;
	uint64_t txnid_unused;
	uint32_t rectype;
	const uint8_t *end, *p;

	r = cookie;
	p = WT_LOG_SKIP_HEADER(logrec->data);
	end = (const uint8_t *)logrec->data + logrec->size;
	WT_UNUSED(firstrecord);

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

	/*
	 * Record the highest LSN we process during the metadata phase.
	 * If not the metadata phase, then stop at that LSN.
	 */
	if (r->metadata_only)
		r->max_rec_lsn = *next_lsnp;
	else if (__wt_log_cmp(lsnp, &r->max_rec_lsn) >= 0)
		return (0);

	switch (rectype) {
	case WT_LOGREC_CHECKPOINT:
		if (r->metadata_only)
			WT_RET(__wt_txn_checkpoint_logread(
			    session, &p, end, &r->ckpt_lsn));
		break;

	case WT_LOGREC_COMMIT:
		if ((ret = __wt_vunpack_uint(
		    &p, WT_PTRDIFF(end, p), &txnid_unused)) != 0)
			WT_RET_MSG(
			    session, ret, "txn_log_recover: unpack failure");
		WT_RET(__txn_commit_apply(r, lsnp, &p, end));
		break;
	}

	return (0);
}
Exemplo n.º 8
0
/*
 * __curlog_logrec --
 *	Callback function from log_scan to get a log record.
 */
static int
__curlog_logrec(WT_SESSION_IMPL *session,
    WT_ITEM *logrec, WT_LSN *lsnp, WT_LSN *next_lsnp,
    void *cookie, int firstrecord)
{
	WT_CURSOR_LOG *cl;

	cl = cookie;
	WT_UNUSED(firstrecord);

	/* Set up the LSNs and take a copy of the log record for the cursor. */
	*cl->cur_lsn = *lsnp;
	*cl->next_lsn = *next_lsnp;
	WT_RET(__wt_buf_set(session, cl->logrec, logrec->data, logrec->size));

	/*
	 * Read the log header.  Set up the step pointers to walk the
	 * operations inside the record.  Get the record type.
	 */
	cl->stepp = WT_LOG_SKIP_HEADER(cl->logrec->data);
	cl->stepp_end = (uint8_t *)cl->logrec->data + logrec->size;
	WT_RET(__wt_logrec_read(session, &cl->stepp, cl->stepp_end,
	    &cl->rectype));

	/* A step count of 0 means the entire record. */
	cl->step_count = 0;

	/*
	 * Unpack the txnid so that we can return each
	 * individual operation for this txnid.
	 */
	if (cl->rectype == WT_LOGREC_COMMIT)
		WT_RET(__wt_vunpack_uint(&cl->stepp,
		    WT_PTRDIFF(cl->stepp_end, cl->stepp), &cl->txnid));
	else {
		/*
		 * Step over anything else.
		 * Setting stepp to NULL causes the next()
		 * method to read a new record on the next call.
		 */
		cl->stepp = NULL;
		cl->txnid = 0;
	}
	return (0);
}
Exemplo n.º 9
0
int
main(void)
{
	const uint8_t *cp;
	uint8_t buf[10], *p;
	uint64_t ncalls, r, r2, s;
	int i;

	ncalls = 0;

	for (i = 0; i < 10000000; i++) {
		for (s = 0; s < 50; s += 5) {
			++ncalls;
			r = 1ULL << s;

#if 1
			p = buf;
			assert(__wt_vpack_uint(&p, sizeof(buf), r) == 0);
			cp = buf;
			assert(__wt_vunpack_uint(&cp, sizeof(buf), &r2) == 0);
#else
			/*
			 * Note: use memmove for comparison because GCC does
			 * aggressive optimization of memcpy and it's difficult
			 * to measure anything.
			 */
			p = buf;
			memmove(p, &r, sizeof(r));
			cp = buf;
			memmove(&r2, cp, sizeof(r2));
#endif
			if (r != r2) {
				fprintf(stderr, "mismatch!\n");
				break;
			}
		}
	}

	printf("Number of calls: %llu\n", (unsigned long long)ncalls);

	return (0);
}
Exemplo n.º 10
0
int main() {
	uint8_t buf[10], *p;
	uint64_t r, r2, ncalls;
	int i, s;

	ncalls = 0;

	for (i = 0; i < 10000000; i++) {
		for (s = 0; s < 50; s += 5) {
			++ncalls;
			r = 1 << s;

#if 1
			p = buf;
			__wt_vpack_uint(NULL, &p, sizeof buf, r);
			p = buf;
			__wt_vunpack_uint(NULL, &p, sizeof buf, &r2);
#else
			/*
			 * Note: use memmove for comparison because GCC does
			 * aggressive optimization of memcpy and it's difficult
			 * to measure anything.
			 */
			p = buf;
			memmove(p, &r, sizeof r);
			p = buf;
			memmove(&r2, p, sizeof r2);
#endif
			if (r != r2) {
				fprintf(stderr, "mismatch!\n");
				break;
			}
		}
	}

	printf("Number of calls: %llu\n", (unsigned long long)ncalls);

	return (0);
}
Exemplo n.º 11
0
/*
 * __las_page_instantiate --
 *	Instantiate lookaside update records in a recently read page.
 */
static int
__las_page_instantiate(WT_SESSION_IMPL *session,
    WT_REF *ref, uint32_t read_id, const uint8_t *addr, size_t addr_size)
{
	WT_CURSOR *cursor;
	WT_CURSOR_BTREE cbt;
	WT_DECL_ITEM(current_key);
	WT_DECL_ITEM(las_addr);
	WT_DECL_ITEM(las_key);
	WT_DECL_ITEM(las_value);
	WT_DECL_RET;
	WT_PAGE *page;
	WT_UPDATE *first_upd, *last_upd, *upd;
	size_t incr, total_incr;
	uint64_t current_recno, las_counter, las_txnid, recno, upd_txnid;
	uint32_t las_id, upd_size, session_flags;
	int exact;
	const uint8_t *p;

	cursor = NULL;
	page = ref->page;
	first_upd = last_upd = upd = NULL;
	total_incr = 0;
	current_recno = recno = WT_RECNO_OOB;
	session_flags = 0;		/* [-Werror=maybe-uninitialized] */

	__wt_btcur_init(session, &cbt);
	__wt_btcur_open(&cbt);

	WT_ERR(__wt_scr_alloc(session, 0, &current_key));
	WT_ERR(__wt_scr_alloc(session, 0, &las_addr));
	WT_ERR(__wt_scr_alloc(session, 0, &las_key));
	WT_ERR(__wt_scr_alloc(session, 0, &las_value));

	/* Open a lookaside table cursor. */
	WT_ERR(__wt_las_cursor(session, &cursor, &session_flags));

	/*
	 * The lookaside records are in key and update order, that is, there
	 * will be a set of in-order updates for a key, then another set of
	 * in-order updates for a subsequent key. We process all of the updates
	 * for a key and then insert those updates into the page, then all the
	 * updates for the next key, and so on.
	 *
	 * Search for the block's unique prefix, stepping through any matching
	 * records.
	 */
	las_addr->data = addr;
	las_addr->size = addr_size;
	las_key->size = 0;
	cursor->set_key(
	    cursor, read_id, las_addr, (uint64_t)0, (uint32_t)0, las_key);
	if ((ret = cursor->search_near(cursor, &exact)) == 0 && exact < 0)
		ret = cursor->next(cursor);
	for (; ret == 0; ret = cursor->next(cursor)) {
		WT_ERR(cursor->get_key(cursor,
		    &las_id, las_addr, &las_counter, &las_txnid, las_key));

		/*
		 * Confirm the search using the unique prefix; if not a match,
		 * we're done searching for records for this page.
		 */
		if (las_id != read_id ||
		    las_addr->size != addr_size ||
		    memcmp(las_addr->data, addr, addr_size) != 0)
			break;

		/*
		 * If the on-page value has become globally visible, this record
		 * is no longer needed.
		 */
		if (__wt_txn_visible_all(session, las_txnid))
			continue;

		/* Allocate the WT_UPDATE structure. */
		WT_ERR(cursor->get_value(
		    cursor, &upd_txnid, &upd_size, las_value));
		WT_ERR(__wt_update_alloc(session,
		    (upd_size == WT_UPDATE_DELETED_VALUE) ? NULL : las_value,
		    &upd, &incr));
		total_incr += incr;
		upd->txnid = upd_txnid;

		switch (page->type) {
		case WT_PAGE_COL_FIX:
		case WT_PAGE_COL_VAR:
			p = las_key->data;
			WT_ERR(__wt_vunpack_uint(&p, 0, &recno));
			if (current_recno == recno)
				break;
			WT_ASSERT(session, current_recno < recno);

			if (first_upd != NULL) {
				WT_ERR(__col_instantiate(session,
				    current_recno, ref, &cbt, first_upd));
				first_upd = NULL;
			}
			current_recno = recno;
			break;
		case WT_PAGE_ROW_LEAF:
			if (current_key->size == las_key->size &&
			    memcmp(current_key->data,
			    las_key->data, las_key->size) == 0)
				break;

			if (first_upd != NULL) {
				WT_ERR(__row_instantiate(session,
				    current_key, ref, &cbt, first_upd));
				first_upd = NULL;
			}
			WT_ERR(__wt_buf_set(session,
			    current_key, las_key->data, las_key->size));
			break;
		WT_ILLEGAL_VALUE_ERR(session);
		}

		/* Append the latest update to the list. */
		if (first_upd == NULL)
			first_upd = last_upd = upd;
		else {
			last_upd->next = upd;
			last_upd = upd;
		}
		upd = NULL;
	}
	WT_ERR_NOTFOUND_OK(ret);

	/* Insert the last set of updates, if any. */
	if (first_upd != NULL)
		switch (page->type) {
		case WT_PAGE_COL_FIX:
		case WT_PAGE_COL_VAR:
			WT_ERR(__col_instantiate(session,
			    current_recno, ref, &cbt, first_upd));
			first_upd = NULL;
			break;
		case WT_PAGE_ROW_LEAF:
			WT_ERR(__row_instantiate(session,
			    current_key, ref, &cbt, first_upd));
			first_upd = NULL;
			break;
		WT_ILLEGAL_VALUE_ERR(session);
		}

	/* Discard the cursor. */
	WT_ERR(__wt_las_cursor_close(session, &cursor, session_flags));

	if (total_incr != 0) {
		__wt_cache_page_inmem_incr(session, page, total_incr);

		/*
		 * We've modified/dirtied the page, but that's not necessary and
		 * if we keep the page clean, it's easier to evict. We leave the
		 * lookaside table updates in place, so if we evict this page
		 * without dirtying it, any future instantiation of it will find
		 * the records it needs. If the page is dirtied before eviction,
		 * then we'll write any needed lookaside table records for the
		 * new location of the page.
		 */
		__wt_page_modify_clear(session, page);
	}

err:	WT_TRET(__wt_las_cursor_close(session, &cursor, session_flags));
	WT_TRET(__wt_btcur_close(&cbt, 1));

	/*
	 * On error, upd points to a single unlinked WT_UPDATE structure,
	 * first_upd points to a list.
	 */
	if (upd != NULL)
		__wt_free(session, upd);
	if (first_upd != NULL)
		__wt_free_update_list(session, first_upd);

	__wt_scr_free(session, &current_key);
	__wt_scr_free(session, &las_addr);
	__wt_scr_free(session, &las_key);
	__wt_scr_free(session, &las_value);

	return (ret);
}
Exemplo n.º 12
0
/*
 * __txn_printlog --
 *	Print a log record in a human-readable format.
 */
static int
__txn_printlog(
    WT_SESSION_IMPL *session, WT_ITEM *logrec, WT_LSN *lsnp, void *cookie)
{
	FILE *out;
	WT_LSN ckpt_lsn;
	const uint8_t *end, *p;
	const char *msg;
	uint64_t txnid;
	uint32_t fileid, rectype;
	int32_t start;

	out = cookie;

	p = (const uint8_t *)logrec->data + offsetof(WT_LOG_RECORD, record);
	end = (const uint8_t *)logrec->data + logrec->size;

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

	if (fprintf(out, "  { \"lsn\" : [%" PRIu32 ",%" PRId64 "],\n",
	    lsnp->file, lsnp->offset) < 0)
		return (errno);

	switch (rectype) {
	case WT_LOGREC_CHECKPOINT:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(IQ), &ckpt_lsn.file, &ckpt_lsn.offset));
		if (fprintf(out, "    \"type\" : \"checkpoint\"\n") < 0 ||
		    fprintf(
		    out, "    \"ckpt_lsn\" : [%" PRIu32 ",%" PRId64 "],\n",
		    ckpt_lsn.file, ckpt_lsn.offset) < 0)
			return (errno);
		break;

	case WT_LOGREC_COMMIT:
		WT_RET(__wt_vunpack_uint(&p, WT_PTRDIFF(end, p), &txnid));
		if (fprintf(out, "    \"type\" : \"commit\"\n") < 0 ||
		    fprintf(out, "    \"txnid\" : %" PRIu64 ",\n", txnid) < 0)
			return (errno);
		WT_RET(__txn_commit_printlog(session, &p, end, out));
		break;

	case WT_LOGREC_FILE_SYNC:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(Ii), &fileid, &start));
		if (fprintf(out, "    \"type\" : \"file_sync\"\n") < 0 ||
		    fprintf(out, "    \"fileid\" : %" PRIu32 "\n",
		    fileid) < 0 ||
		    fprintf(out, "    \"start\" : %" PRId32 "\n", start) < 0)
			return (errno);
		break;

	case WT_LOGREC_MESSAGE:
		WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p),
		    WT_UNCHECKED_STRING(S), &msg));
		if (fprintf(out, "    \"type\" : \"message\"\n") < 0 ||
		    fprintf(out, "    \"message\" : \"%s\"\n", msg) < 0)
			return (errno);
		break;
	}

	if (fprintf(out, "  },\n") < 0)
		return (errno);

	return (0);
}
Exemplo n.º 13
0
/*
 * __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);
}
Exemplo n.º 14
0
void
test_value(int64_t val)
{
	const uint8_t *cp;
	uint8_t buf[WT_INTPACK64_MAXSIZE + 8];	/* -Werror=array-bounds */
	uint8_t *p;
	int64_t sinput, soutput;
	uint64_t uinput, uoutput;
	size_t used_len;

	memset(buf, 0xff, sizeof(buf));	/* -Werror=maybe-uninitialized */
	sinput = val;
	soutput = 0;	/* -Werror=maybe-uninitialized */

	/*
	 * Required on some systems to pull in parts of the library
	 * for which we have data references.
	 */
	testutil_check(__wt_library_init());

	p = buf;
	testutil_check(__wt_vpack_int(&p, sizeof(buf), sinput));
	used_len = (size_t)(p - buf);
	testutil_assert(used_len <= WT_INTPACK64_MAXSIZE);
	cp = buf;
	testutil_check(__wt_vunpack_int(&cp, used_len, &soutput));
	/* Ensure we got the correct value back */
	if (sinput != soutput) {
		fprintf(stderr,
		    "mismatch %" PRId64 ", %" PRId64 "\n", sinput, soutput);
		abort();
	}
	/* Ensure that decoding used the correct amount of buffer */
	if (cp != p) {
		fprintf(stderr,
		    "Unpack consumed wrong size for %" PRId64
		    ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n",
		    sinput, used_len, cp > p ?
		    used_len + (size_t)(cp - p) : /* More than buf used */
		    used_len - (size_t)(p - cp)); /* Less than buf used */
		abort();
	}

	/* Test unsigned, convert negative into bigger positive values */
	uinput = (uint64_t)val;

	p = buf;
	testutil_check(__wt_vpack_uint(&p, sizeof(buf), uinput));
	used_len = (size_t)(p - buf);
	testutil_assert(used_len <= WT_INTPACK64_MAXSIZE);
	cp = buf;
	testutil_check(__wt_vunpack_uint(&cp, sizeof(buf), &uoutput));
	/* Ensure we got the correct value back */
	if (sinput != soutput) {
		fprintf(stderr,
		    "mismatch %" PRId64 ", %" PRId64 "\n", sinput, soutput);
		abort();
	}
	/* Ensure that decoding used the correct amount of buffer */
	if (cp != p) {
		fprintf(stderr,
		    "Unpack consumed wrong size for %" PRId64
		    ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n",
		    sinput, used_len, cp > p ?
		    used_len + (size_t)(cp - p) :
		    used_len - (size_t)(p - cp));
		abort();
	}
}