示例#1
0
/*
 * __wt_block_ckpt_to_buffer --
 *	Convert the components into its checkpoint cookie.
 */
int
__wt_block_ckpt_to_buffer(WT_SESSION_IMPL *session,
    WT_BLOCK *block, uint8_t **pp, WT_BLOCK_CKPT *ci)
{
	uint64_t a;

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

	(*pp)[0] = ci->version;
	(*pp)++;

	WT_RET(__wt_block_addr_to_buffer(block, pp,
	    ci->root_offset, ci->root_size, ci->root_cksum));
	WT_RET(__wt_block_addr_to_buffer(block, pp,
	    ci->alloc.offset, ci->alloc.size, ci->alloc.cksum));
	WT_RET(__wt_block_addr_to_buffer(block, pp,
	    ci->avail.offset, ci->avail.size, ci->avail.cksum));
	WT_RET(__wt_block_addr_to_buffer(block, pp,
	    ci->discard.offset, ci->discard.size, ci->discard.cksum));
	a = (uint64_t)ci->file_size;
	WT_RET(__wt_vpack_uint(pp, 0, a));
	a = (uint64_t)ci->ckpt_size;
	WT_RET(__wt_vpack_uint(pp, 0, a));

	return (0);
}
示例#2
0
int
main(void)
{
	uint8_t buf[10], *p, *end;
	int64_t i;

	for (i = 1; i < 1LL << 60; i <<= 1) {
		end = buf;
		testutil_check(
		    __wt_vpack_uint(&end, sizeof(buf), (uint64_t)i));
		printf("%" PRId64 " ", i);
		for (p = buf; p < end; p++)
			printf("%02x", *p);
		printf("\n");

		end = buf;
		testutil_check(__wt_vpack_int(&end, sizeof(buf), -i));
		printf("%" PRId64 " ", -i);
		for (p = buf; p < end; p++)
			printf("%02x", *p);
		printf("\n");
	}

	return (0);
}
示例#3
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();
	}
}
示例#4
0
/*
 * __wt_block_addr_to_buffer --
 *	Convert the filesystem components into its address cookie.
 */
int
__wt_block_addr_to_buffer(WT_BLOCK *block,
    uint8_t **pp, wt_off_t offset, uint32_t size, uint32_t checksum)
{
	uint64_t o, s, c;

	/* See the comment above: this is the reverse operation. */
	if (size == 0) {
		o = WT_BLOCK_INVALID_OFFSET;
		s = c = 0;
	} else {
		o = (uint64_t)offset / block->allocsize - 1;
		s = size / block->allocsize;
		c = checksum;
	}
	WT_RET(__wt_vpack_uint(pp, 0, o));
	WT_RET(__wt_vpack_uint(pp, 0, s));
	WT_RET(__wt_vpack_uint(pp, 0, c));
	return (0);
}
示例#5
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);
}
示例#6
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);
}
示例#7
0
/*
 * __wt_txn_checkpoint_log --
 *	Write a log record for a checkpoint operation.
 */
int
__wt_txn_checkpoint_log(
    WT_SESSION_IMPL *session, int full, uint32_t flags, WT_LSN *lsnp)
{
	WT_DECL_RET;
	WT_DECL_ITEM(logrec);
	WT_LSN *ckpt_lsn;
	WT_TXN *txn;
	const char *fmt = WT_UNCHECKED_STRING(IIQIU);
	uint8_t *end, *p;
	size_t recsize;
	uint32_t i, rectype = WT_LOGREC_CHECKPOINT;

	txn = &session->txn;
	ckpt_lsn = &txn->ckpt_lsn;

	/*
	 * If this is a file sync, log it unless there is a full checkpoint in
	 * progress.
	 */
	if (!full) {
		if (txn->full_ckpt) {
			if (lsnp != NULL)
				*lsnp = *ckpt_lsn;
			return (0);
		} else
			return (__txn_log_file_sync(session, flags, lsnp));
	}

	switch (flags) {
	case WT_TXN_LOG_CKPT_PREPARE:
		txn->full_ckpt = 1;
		*ckpt_lsn = S2C(session)->log->alloc_lsn;
		break;

	case WT_TXN_LOG_CKPT_START:
		/* Take a copy of the transaction snapshot. */
		txn->ckpt_nsnapshot = txn->snapshot_count;
		recsize = txn->ckpt_nsnapshot * WT_INTPACK64_MAXSIZE;
		WT_ERR(__wt_scr_alloc(session, recsize, &txn->ckpt_snapshot));
		p = txn->ckpt_snapshot->mem;
		end = p + recsize;
		for (i = 0; i < txn->snapshot_count; i++)
			WT_ERR(__wt_vpack_uint(
			    &p, WT_PTRDIFF(end, p), txn->snapshot[i]));
		break;

	case WT_TXN_LOG_CKPT_STOP:
		/*
		 * During a clean connection close, we get here without the
		 * prepare or start steps.  In that case, log the current LSN
		 * as the checkpoint LSN.
		 */
		if (!txn->full_ckpt) {
			txn->ckpt_nsnapshot = 0;
			*ckpt_lsn = S2C(session)->log->alloc_lsn;
		}

		/* Write the checkpoint log record. */
		WT_ERR(__wt_struct_size(session, &recsize, fmt,
		    rectype, ckpt_lsn->file, ckpt_lsn->offset,
		    txn->ckpt_nsnapshot, &txn->ckpt_snapshot));
		WT_ERR(__wt_logrec_alloc(session, recsize, &logrec));

		WT_ERR(__wt_struct_pack(session,
		    (uint8_t *)logrec->data + logrec->size, recsize, fmt,
		    rectype, ckpt_lsn->file, ckpt_lsn->offset,
		    txn->ckpt_nsnapshot, &txn->ckpt_snapshot));
		logrec->size += (uint32_t)recsize;
		WT_ERR(__wt_log_write(session, logrec, lsnp, 0));

		/*
		 * If this full checkpoint completed successfully and there is
		 * no hot backup in progress, tell the logging subsystem the
		 * checkpoint LSN so that it can archive.
		 */
		if (!S2C(session)->hot_backup)
			WT_ERR(__wt_log_ckpt(session, ckpt_lsn));

		/* FALLTHROUGH */
	case WT_TXN_LOG_CKPT_FAIL:
		/* Cleanup any allocated resources */
		INIT_LSN(ckpt_lsn);
		txn->ckpt_nsnapshot = 0;
		__wt_scr_free(&txn->ckpt_snapshot);
		txn->full_ckpt = 0;
		break;
	}

err:	__wt_logrec_free(session, &logrec);
	return (ret);
}
示例#8
0
文件: txn_log.c 项目: DINKIN/mongo
/*
 * __wt_txn_checkpoint_log --
 *	Write a log record for a checkpoint operation.
 */
int
__wt_txn_checkpoint_log(
    WT_SESSION_IMPL *session, bool full, uint32_t flags, WT_LSN *lsnp)
{
	WT_CONNECTION_IMPL *conn;
	WT_DECL_ITEM(logrec);
	WT_DECL_RET;
	WT_ITEM *ckpt_snapshot, empty;
	WT_LSN *ckpt_lsn;
	WT_TXN *txn;
	WT_TXN_GLOBAL *txn_global;
	uint8_t *end, *p;
	size_t recsize;
	uint32_t i, rectype;
	const char *fmt;

	conn = S2C(session);
	txn_global = &conn->txn_global;
	txn = &session->txn;
	ckpt_lsn = &txn->ckpt_lsn;

	/*
	 * If this is a file sync, log it unless there is a full checkpoint in
	 * progress.
	 */
	if (!full) {
		if (txn->full_ckpt) {
			if (lsnp != NULL)
				*lsnp = *ckpt_lsn;
			return (0);
		}
		return (__txn_log_file_sync(session, flags, lsnp));
	}

	switch (flags) {
	case WT_TXN_LOG_CKPT_PREPARE:
		txn->full_ckpt = true;

		if (conn->compat_major >= WT_LOG_V2) {
			/*
			 * Write the system log record containing a checkpoint
			 * start operation.
			 */
			rectype = WT_LOGREC_SYSTEM;
			fmt = WT_UNCHECKED_STRING(I);
			WT_ERR(__wt_struct_size(
			    session, &recsize, fmt, rectype));
			WT_ERR(__wt_logrec_alloc(session, recsize, &logrec));

			WT_ERR(__wt_struct_pack(session,
			    (uint8_t *)logrec->data + logrec->size, recsize,
			    fmt, rectype));
			logrec->size += (uint32_t)recsize;
			WT_ERR(__wt_logop_checkpoint_start_pack(
			    session, logrec));
			WT_ERR(__wt_log_write(session, logrec, ckpt_lsn, 0));
		} else {
			WT_ERR(__wt_log_printf(session,
			    "CHECKPOINT: Starting record"));
			WT_ERR(__wt_log_flush_lsn(session, ckpt_lsn, true));
		}

		/*
		 * We take and immediately release the visibility lock.
		 * Acquiring the write lock guarantees that any transaction
		 * that has written to the log has also made its transaction
		 * visible at this time.
		 */
		__wt_writelock(session, &txn_global->visibility_rwlock);
		__wt_writeunlock(session, &txn_global->visibility_rwlock);

		/*
		 * We need to make sure that the log records in the checkpoint
		 * LSN are on disk.  In particular to make sure that the
		 * current log file exists.
		 */
		WT_ERR(__wt_log_force_sync(session, ckpt_lsn));
		break;
	case WT_TXN_LOG_CKPT_START:
		/* Take a copy of the transaction snapshot. */
		txn->ckpt_nsnapshot = txn->snapshot_count;
		recsize = (size_t)txn->ckpt_nsnapshot * WT_INTPACK64_MAXSIZE;
		WT_ERR(__wt_scr_alloc(session, recsize, &txn->ckpt_snapshot));
		p = txn->ckpt_snapshot->mem;
		end = p + recsize;
		for (i = 0; i < txn->snapshot_count; i++)
			WT_ERR(__wt_vpack_uint(
			    &p, WT_PTRDIFF(end, p), txn->snapshot[i]));
		break;
	case WT_TXN_LOG_CKPT_STOP:
		/*
		 * During a clean connection close, we get here without the
		 * prepare or start steps.  In that case, log the current LSN
		 * as the checkpoint LSN.
		 */
		if (!txn->full_ckpt) {
			txn->ckpt_nsnapshot = 0;
			WT_CLEAR(empty);
			ckpt_snapshot = &empty;
			WT_ERR(__wt_log_flush_lsn(session, ckpt_lsn, true));
		} else
			ckpt_snapshot = txn->ckpt_snapshot;

		/* Write the checkpoint log record. */
		rectype = WT_LOGREC_CHECKPOINT;
		fmt = WT_UNCHECKED_STRING(IIIIu);
		WT_ERR(__wt_struct_size(session, &recsize,
		    fmt, rectype, ckpt_lsn->l.file, ckpt_lsn->l.offset,
		    txn->ckpt_nsnapshot, ckpt_snapshot));
		WT_ERR(__wt_logrec_alloc(session, recsize, &logrec));

		WT_ERR(__wt_struct_pack(session,
		    (uint8_t *)logrec->data + logrec->size, recsize,
		    fmt, rectype, ckpt_lsn->l.file, ckpt_lsn->l.offset,
		    txn->ckpt_nsnapshot, ckpt_snapshot));
		logrec->size += (uint32_t)recsize;
		WT_ERR(__wt_log_write(session, logrec, lsnp,
		    F_ISSET(conn, WT_CONN_CKPT_SYNC) ?
		    WT_LOG_FSYNC : 0));

		/*
		 * If this full checkpoint completed successfully and there is
		 * no hot backup in progress and this is not an unclean
		 * recovery, tell the logging subsystem the checkpoint LSN so
		 * that it can archive.  Do not update the logging checkpoint
		 * LSN if this is during a clean connection close, only during
		 * a full checkpoint.  A clean close may not update any
		 * metadata LSN and we do not want to archive in that case.
		 */
		if (!conn->hot_backup &&
		    (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DIRTY) ||
		    FLD_ISSET(conn->log_flags, WT_CONN_LOG_FORCE_DOWNGRADE)) &&
		    txn->full_ckpt)
			__wt_log_ckpt(session, ckpt_lsn);

		/* FALLTHROUGH */
	case WT_TXN_LOG_CKPT_CLEANUP:
		/* Cleanup any allocated resources */
		WT_INIT_LSN(ckpt_lsn);
		txn->ckpt_nsnapshot = 0;
		__wt_scr_free(session, &txn->ckpt_snapshot);
		txn->full_ckpt = false;
		break;
	WT_ILLEGAL_VALUE_ERR(session);
	}

err:	__wt_logrec_free(session, &logrec);
	return (ret);
}
示例#9
0
/*
 * __wt_txn_checkpoint_log --
 *	Write a log record for a checkpoint operation.
 */
int
__wt_txn_checkpoint_log(
    WT_SESSION_IMPL *session, bool full, uint32_t flags, WT_LSN *lsnp)
{
	WT_DECL_ITEM(logrec);
	WT_DECL_RET;
	WT_ITEM *ckpt_snapshot, empty;
	WT_LSN *ckpt_lsn;
	WT_TXN *txn;
	uint8_t *end, *p;
	size_t recsize;
	uint32_t i, rectype = WT_LOGREC_CHECKPOINT;
	const char *fmt = WT_UNCHECKED_STRING(IIQIU);

	txn = &session->txn;
	ckpt_lsn = &txn->ckpt_lsn;

	/*
	 * If this is a file sync, log it unless there is a full checkpoint in
	 * progress.
	 */
	if (!full) {
		if (txn->full_ckpt) {
			if (lsnp != NULL)
				*lsnp = *ckpt_lsn;
			return (0);
		}
		return (__txn_log_file_sync(session, flags, lsnp));
	}

	switch (flags) {
	case WT_TXN_LOG_CKPT_PREPARE:
		txn->full_ckpt = true;
		WT_ERR(__wt_log_flush_lsn(session, ckpt_lsn, true));
		/*
		 * We need to make sure that the log records in the checkpoint
		 * LSN are on disk.  In particular to make sure that the
		 * current log file exists.
		 */
		WT_ERR(__wt_log_force_sync(session, ckpt_lsn));
		break;
	case WT_TXN_LOG_CKPT_START:
		/* Take a copy of the transaction snapshot. */
		txn->ckpt_nsnapshot = txn->snapshot_count;
		recsize = txn->ckpt_nsnapshot * WT_INTPACK64_MAXSIZE;
		WT_ERR(__wt_scr_alloc(session, recsize, &txn->ckpt_snapshot));
		p = txn->ckpt_snapshot->mem;
		end = p + recsize;
		for (i = 0; i < txn->snapshot_count; i++)
			WT_ERR(__wt_vpack_uint(
			    &p, WT_PTRDIFF(end, p), txn->snapshot[i]));
		break;
	case WT_TXN_LOG_CKPT_STOP:
		/*
		 * During a clean connection close, we get here without the
		 * prepare or start steps.  In that case, log the current LSN
		 * as the checkpoint LSN.
		 */
		if (!txn->full_ckpt) {
			txn->ckpt_nsnapshot = 0;
			WT_CLEAR(empty);
			ckpt_snapshot = &empty;
			WT_ERR(__wt_log_flush_lsn(session, ckpt_lsn, true));
		} else
			ckpt_snapshot = txn->ckpt_snapshot;

		/* Write the checkpoint log record. */
		WT_ERR(__wt_struct_size(session, &recsize, fmt,
		    rectype, ckpt_lsn->file, ckpt_lsn->offset,
		    txn->ckpt_nsnapshot, ckpt_snapshot));
		WT_ERR(__wt_logrec_alloc(session, recsize, &logrec));

		WT_ERR(__wt_struct_pack(session,
		    (uint8_t *)logrec->data + logrec->size, recsize, fmt,
		    rectype, ckpt_lsn->file, ckpt_lsn->offset,
		    txn->ckpt_nsnapshot, ckpt_snapshot));
		logrec->size += (uint32_t)recsize;
		WT_ERR(__wt_log_write(session, logrec, lsnp,
		    F_ISSET(S2C(session), WT_CONN_CKPT_SYNC) ?
		    WT_LOG_FSYNC : 0));

		/*
		 * If this full checkpoint completed successfully and there is
		 * no hot backup in progress, tell the logging subsystem the
		 * checkpoint LSN so that it can archive.  Do not update the
		 * logging checkpoint LSN if this is during a clean connection
		 * close, only during a full checkpoint.  A clean close may not
		 * update any metadata LSN and we do not want to archive in
		 * that case.
		 */
		if (!S2C(session)->hot_backup && txn->full_ckpt)
			WT_ERR(__wt_log_ckpt(session, ckpt_lsn));

		/* FALLTHROUGH */
	case WT_TXN_LOG_CKPT_CLEANUP:
		/* Cleanup any allocated resources */
		WT_INIT_LSN(ckpt_lsn);
		txn->ckpt_nsnapshot = 0;
		__wt_scr_free(session, &txn->ckpt_snapshot);
		txn->full_ckpt = false;
		break;
	WT_ILLEGAL_VALUE_ERR(session);
	}

err:	__wt_logrec_free(session, &logrec);
	return (ret);
}
示例#10
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();
	}
}