コード例 #1
0
ファイル: meta_ckpt.c プロジェクト: DINKIN/mongo
/*
 * __wt_meta_ckptlist_get --
 *	Load all available checkpoint information for a file.
 */
int
__wt_meta_ckptlist_get(
    WT_SESSION_IMPL *session, const char *fname, WT_CKPT **ckptbasep)
{
	WT_CKPT *ckpt, *ckptbase;
	WT_CONFIG ckptconf;
	WT_CONFIG_ITEM k, v;
	WT_DECL_ITEM(buf);
	WT_DECL_RET;
	size_t allocated, slot;
	char *config;

	*ckptbasep = NULL;

	ckptbase = NULL;
	allocated = slot = 0;
	config = NULL;

	/* Retrieve the metadata information for the file. */
	WT_RET(__wt_metadata_search(session, fname, &config));

	/* Load any existing checkpoints into the array. */
	WT_ERR(__wt_scr_alloc(session, 0, &buf));
	if (__wt_config_getones(session, config, "checkpoint", &v) == 0) {
		__wt_config_subinit(session, &ckptconf, &v);
		for (; __wt_config_next(&ckptconf, &k, &v) == 0; ++slot) {
			WT_ERR(__wt_realloc_def(
			    session, &allocated, slot + 1, &ckptbase));
			ckpt = &ckptbase[slot];

			WT_ERR(__ckpt_load(session, &k, &v, ckpt));
		}
	}

	/*
	 * Allocate an extra slot for a new value, plus a slot to mark the end.
	 *
	 * This isn't very clean, but there's necessary cooperation between the
	 * schema layer (that maintains the list of checkpoints), the btree
	 * layer (that knows when the root page is written, creating a new
	 * checkpoint), and the block manager (which actually creates the
	 * checkpoint).  All of that cooperation is handled in the WT_CKPT
	 * structure referenced from the WT_BTREE structure.
	 */
	WT_ERR(__wt_realloc_def(session, &allocated, slot + 2, &ckptbase));

	/* Sort in creation-order. */
	qsort(ckptbase, slot, sizeof(WT_CKPT), __ckpt_compare_order);

	/* Return the array to our caller. */
	*ckptbasep = ckptbase;

	if (0) {
err:		__wt_meta_ckptlist_free(session, &ckptbase);
	}
	__wt_free(session, config);
	__wt_scr_free(session, &buf);

	return (ret);
}
コード例 #2
0
ファイル: session_salvage.c プロジェクト: DINKIN/mongo
/*
 * __wt_salvage --
 *	Salvage a single file.
 */
int
__wt_salvage(WT_SESSION_IMPL *session, const char *cfg[])
{
	WT_CKPT *ckptbase;
	WT_DATA_HANDLE *dhandle;
	WT_DECL_RET;

	dhandle = session->dhandle;

	/*
	 * XXX
	 * The salvage process reads and discards previous checkpoints, so the
	 * underlying block manager has to ignore any previous checkpoint
	 * entries when creating a new checkpoint, in other words, we can't use
	 * the metadata checkpoint list, it has all of those checkpoint listed
	 * and we don't care about them.  Build a clean checkpoint list and use
	 * it instead.
	 *
	 * Don't first clear the metadata checkpoint list and call the function
	 * to get a list of checkpoints: a crash between clearing the metadata
	 * checkpoint list and creating a new checkpoint list would look like a
	 * create or open of a file without a checkpoint to roll-forward from,
	 * and the contents of the file would be discarded.
	 */
	WT_RET(__wt_calloc_def(session, 2, &ckptbase));
	WT_ERR(__wt_strdup(session, WT_CHECKPOINT, &ckptbase[0].name));
	F_SET(&ckptbase[0], WT_CKPT_ADD);

	WT_ERR(__wt_bt_salvage(session, ckptbase, cfg));

	/*
	 * If no checkpoint was created, well, it's probably bad news, but there
	 * is nothing to do but clear any recorded checkpoints for the file.  If
	 * a checkpoint was created, life is good, replace any existing list of
	 * checkpoints with the single new one.
	 */
	if (ckptbase[0].raw.data == NULL)
		WT_ERR(__wt_meta_checkpoint_clear(session, dhandle->name));
	else
		WT_ERR(__wt_meta_ckptlist_set(
		    session, dhandle->name, ckptbase, NULL));

err:	__wt_meta_ckptlist_free(session, &ckptbase);
	return (ret);
}
コード例 #3
0
ファイル: meta_ckpt.c プロジェクト: zhliu03/wiredtiger
/*
 * __wt_meta_ckptlist_get --
 *	Load all available checkpoint information for a file.
 */
int
__wt_meta_ckptlist_get(
    WT_SESSION_IMPL *session, const char *fname, WT_CKPT **ckptbasep)
{
	WT_CKPT *ckpt, *ckptbase;
	WT_CONFIG ckptconf;
	WT_CONFIG_ITEM a, k, v;
	WT_DECL_RET;
	WT_ITEM *buf;
	size_t allocated, slot;
	const char *config;
	char timebuf[64];

	*ckptbasep = NULL;

	buf = NULL;
	ckptbase = NULL;
	allocated = slot = 0;
	config = NULL;

	/* Retrieve the metadata information for the file. */
	WT_RET(__wt_metadata_read(session, fname, &config));

	/* Load any existing checkpoints into the array. */
	WT_ERR(__wt_scr_alloc(session, 0, &buf));
	if (__wt_config_getones(session, config, "checkpoint", &v) == 0 &&
	    __wt_config_subinit(session, &ckptconf, &v) == 0)
		for (; __wt_config_next(&ckptconf, &k, &v) == 0; ++slot) {
			if (slot * sizeof(WT_CKPT) == allocated)
				WT_ERR(__wt_realloc(session, &allocated,
				    (slot + 50) * sizeof(WT_CKPT), &ckptbase));
			ckpt = &ckptbase[slot];

			/*
			 * Copy the name, address (raw and hex), order and time
			 * into the slot.  If there's no address, it's a fake.
			 */
			WT_ERR(
			    __wt_strndup(session, k.str, k.len, &ckpt->name));

			WT_ERR(__wt_config_subgets(session, &v, "addr", &a));
			WT_ERR(
			    __wt_buf_set(session, &ckpt->addr, a.str, a.len));
			if (a.len == 0)
				F_SET(ckpt, WT_CKPT_FAKE);
			else
				WT_ERR(__wt_nhex_to_raw(
				    session, a.str, a.len, &ckpt->raw));

			WT_ERR(__wt_config_subgets(session, &v, "order", &a));
			if (a.val == 0)
				goto format;
			ckpt->order = a.val;

			WT_ERR(__wt_config_subgets(session, &v, "time", &a));
			if (a.len == 0)
				goto format;
			if (a.len > sizeof(timebuf) - 1)
				goto format;
			memcpy(timebuf, a.str, a.len);
			timebuf[a.len] = '\0';
			if (sscanf(timebuf, "%" SCNuMAX, &ckpt->sec) != 1)
				goto format;

			WT_ERR(__wt_config_subgets(session, &v, "size", &a));
			ckpt->ckpt_size = (uint64_t)a.val;
		}

	/*
	 * Allocate an extra slot for a new value, plus a slot to mark the end.
	 *
	 * This isn't very clean, but there's necessary cooperation between the
	 * schema layer (that maintains the list of checkpoints), the btree
	 * layer (that knows when the root page is written, creating a new
	 * checkpoint), and the block manager (which actually creates the
	 * checkpoint).  All of that cooperation is handled in the WT_CKPT
	 * structure referenced from the WT_BTREE structure.
	 */
	if ((slot + 2) * sizeof(WT_CKPT) > allocated)
		WT_ERR(__wt_realloc(session, &allocated,
		    (slot + 2) * sizeof(WT_CKPT), &ckptbase));

	/* Sort in creation-order. */
	qsort(ckptbase, slot, sizeof(WT_CKPT), __ckpt_compare_order);

	/* Return the array to our caller. */
	*ckptbasep = ckptbase;

	if (0) {
format:		WT_ERR_MSG(session, WT_ERROR, "corrupted checkpoint list");
err:		__wt_meta_ckptlist_free(session, ckptbase);
	}
	__wt_free(session, config);
	__wt_scr_free(&buf);

	return (ret);
}