/*-
 * Copyright (c) 2014-2018 MongoDB, Inc.
 * Copyright (c) 2008-2014 WiredTiger, Inc.
 *	All rights reserved.
 *
 * See the file LICENSE for redistribution information.
 */

#include "wt_internal.h"

/*
 * __wt_log_system_record --
 *	Write a system log record for the previous LSN.
 */
int
__wt_log_system_record(WT_SESSION_IMPL *session, WT_FH *log_fh, WT_LSN *lsn)
{
	WT_DECL_ITEM(logrec_buf);
	WT_DECL_RET;
	WT_LOG *log;
	WT_LOGSLOT tmp;
	WT_LOG_RECORD *logrec;
	WT_MYSLOT myslot;
	size_t recsize;
	uint32_t rectype;
	const char *fmt;

	log = S2C(session)->log;
	rectype = WT_LOGREC_SYSTEM;
	fmt = WT_UNCHECKED_STRING(I);

	WT_RET(__wt_logrec_alloc(session, log->allocsize, &logrec_buf));
	memset((uint8_t *)logrec_buf->mem, 0, log->allocsize);

	WT_ERR(__wt_struct_size(session, &recsize, fmt, rectype));
	WT_ERR(__wt_struct_pack(session,
	    (uint8_t *)logrec_buf->data + logrec_buf->size, recsize, fmt,
	    rectype));
	logrec_buf->size += recsize;
	WT_ERR(__wt_logop_prev_lsn_pack(session, logrec_buf, lsn));
	WT_ASSERT(session, logrec_buf->size <= log->allocsize);

	logrec = (WT_LOG_RECORD *)logrec_buf->mem;

	/*
	 * We know system records are this size.  And we have to adjust
	 * the size now because we're not going through the normal log
	 * write path and the packing functions needed the correct offset
	 * earlier.
	 */
	logrec_buf->size = logrec->len = log->allocsize;

	/* We do not compress nor encrypt this record. */
	logrec->checksum = 0;
	logrec->flags = 0;
	__wt_log_record_byteswap(logrec);
	logrec->checksum = __wt_checksum(logrec, log->allocsize);
#ifdef WORDS_BIGENDIAN
	logrec->checksum = __wt_bswap32(logrec->checksum);
#endif
	WT_CLEAR(tmp);
	memset(&myslot, 0, sizeof(myslot));
	myslot.slot = &tmp;
	__wt_log_slot_activate(session, &tmp);
	/*
	 * Override the file handle to the one we're using.
	 */
	tmp.slot_fh = log_fh;
	WT_ERR(__wt_log_fill(session, &myslot, true, logrec_buf, NULL));
err:	__wt_logrec_free(session, &logrec_buf);
	return (ret);
}

/*
 * __wt_log_recover_system --
 *	Process a system log record for the previous LSN in recovery.
 */
int
__wt_log_recover_system(WT_SESSION_IMPL *session,
    const uint8_t **pp, const uint8_t *end, WT_LSN *lsnp)
{
	WT_DECL_RET;

	if ((ret = __wt_logop_prev_lsn_unpack(session, pp, end, lsnp)) != 0)
		WT_RET_MSG(session, ret,
		    "log_recover_prevlsn: unpack failure");

	return (0);
}

/*
 * __wt_verbose_dump_log --
 *	Dump information about the logging subsystem.
 */
int
__wt_verbose_dump_log(WT_SESSION_IMPL *session)
{
	WT_CONNECTION_IMPL *conn;
	WT_LOG *log;

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

	WT_RET(__wt_msg(session, "%s", WT_DIVIDER));
	WT_RET(__wt_msg(session, "Logging subsystem: Enabled: %s",
	    FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) ? "yes" : "no"));
	if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))
		return (0);
	/*
	 * Logging is enabled, print out the other information.
	 */
	WT_RET(__wt_msg(session, "Archiving: %s",
	    FLD_ISSET(conn->log_flags, WT_CONN_LOG_ARCHIVE) ? "yes" : "no"));
	WT_RET(__wt_msg(session, "Running downgraded: %s",
	    FLD_ISSET(conn->log_flags, WT_CONN_LOG_DOWNGRADED) ? "yes" : "no"));
	WT_RET(__wt_msg(session, "Zero fill files: %s",
	    FLD_ISSET(conn->log_flags, WT_CONN_LOG_ZERO_FILL) ? "yes" : "no"));
	WT_RET(__wt_msg(session, "Pre-allocate files: %s",
	    conn->log_prealloc > 0 ? "yes" : "no"));
	WT_RET(__wt_msg(session, "Logging directory: %s", conn->log_path));
	WT_RET(__wt_msg(session, "Logging maximum file size: %" PRId64,
	    (int64_t)conn->log_file_max));
	WT_RET(__wt_msg(session, "Log sync setting: %s",
	    !FLD_ISSET(conn->txn_logsync, WT_LOG_SYNC_ENABLED) ? "none" :
	    FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC) ? "dsync" :
	    FLD_ISSET(conn->txn_logsync, WT_LOG_FLUSH) ? "write to OS" :
	    FLD_ISSET(conn->txn_logsync, WT_LOG_FSYNC) ?
	    "fsync to disk": "unknown sync setting"));
	WT_RET(__wt_msg(session, "Log record allocation alignment: %" PRIu32,
	    log->allocsize));
	WT_RET(__wt_msg(session, "Current log file number: %" PRIu32,
	    log->fileid));
	WT_RET(__wt_msg(session, "Current log version number: %" PRIu16,
	    log->log_version));
	WT_RET(WT_LSN_MSG(&log->alloc_lsn, "Next allocation"));
	WT_RET(WT_LSN_MSG(&log->bg_sync_lsn, "Last background sync"));
	WT_RET(WT_LSN_MSG(&log->ckpt_lsn, "Last checkpoint"));
	WT_RET(WT_LSN_MSG(&log->sync_dir_lsn, "Last directory sync"));
	WT_RET(WT_LSN_MSG(&log->sync_lsn, "Last sync"));
	WT_RET(WT_LSN_MSG(&log->trunc_lsn, "Recovery truncate"));
	WT_RET(WT_LSN_MSG(&log->write_lsn, "Last written"));
	WT_RET(WT_LSN_MSG(&log->write_start_lsn, "Start of last written"));
	/*
	 * If we wanted a dump of the slots, it would go here. Walking
	 * the slot pool may not require a lock since they're statically
	 * allocated, but output could be inconsistent without it.
	 */

	return (0);
}
