Esempio n. 1
0
/* Kill old shadow tree. */
static int
callback_unshadow(void * cookie)
{
	struct write_cookie * WC = cookie;
	struct btree * T = WC->T;
	struct node * root_shadow;

	/*
	 * Grab the root of the shadow tree, and use the (now clean) dirty
	 * tree as the shadow tree henceforth.
	 */
	root_shadow = T->root_shadow;
	T->root_shadow = T->root_dirty;
	btree_node_lock(T, T->root_shadow);

	/* Kill the old shadow tree, if there was one. */
	if (root_shadow != NULL) {
		/* This isn't a root any more, so release the root lock. */
		btree_node_unlock(T, root_shadow);

		/*
		 * Traverse the tree, re-pointing clean children at their
		 * dirty parents and freeing shadow nodes.
		 */
		unshadow(T, root_shadow);
	}

	/* Update number-of-pages-used value. */
	T->npages = T->nextblk - T->root_dirty->oldestleaf;

	/*
	 * We could issue a FREE call here, but since FREE is only advisory
	 * we need to call it elsewhere as well in order to avoid having data
	 * permanently stored even when it could all be freed.  Since we're
	 * calling FREE elsewhere anyway, don't bother calling it here.
	 */

	/* Register post-sync callback to be performed. */
	if (!events_immediate_register(WC->callback, WC->cookie, 0))
		goto err1;

	/* Free cookie. */
	free(WC);

	/* Success! */
	return (0);

err1:
	free(WC);

	/* Failure! */
	return (-1);
}
Esempio n. 2
0
/* Try to launch a connection.  Free the cookie on fatal errors. */
static int
tryconnect(struct connect_cookie * C)
{

	/* Try addresses until we find one which doesn't fail immediately. */
	for (; C->sas[0] != NULL; C->sas++) {
		/* Can we try to connect to this address? */
		if ((C->s = sock_connect_nb(C->sas[0])) != -1)
			break;
	}

	/* Did we run out of addresses to try? */
	if (C->sas[0] == NULL)
		goto failed;

	/* Wait until this socket connects or fails to do so. */
	if (events_network_register(callback_connect, C, C->s,
	    EVENTS_NETWORK_OP_WRITE))
		goto err1;

	/* Success! */
	return (0);

failed:
	/* Schedule a callback. */
	if ((C->cookie_immediate =
	    events_immediate_register(docallback, C, 0)) == NULL)
		goto err1;

	/* Failure successfully handled. */
	return (0);

err1:
	if (C->s != -1)
		close(C->s);
	free(C);

	/* Fatal error. */
	return (-1);
}
Esempio n. 3
0
/* Callback for btree_sync when write is complete. */
static int
callback_append(void * cookie, int failed, int status, uint64_t blkno)
{
	struct write_cookie * WC = cookie;
	struct btree * T = WC->T;

	/* Throw a fit if we didn't manage to write the pages. */
	if (failed)
		goto err1;
	if (status) {
		warn0("Failed to write dirty nodes to backing store");
		goto err1;
	}

	/* Record the next available block number. */
	T->nextblk = blkno;

	/* Mark the nodes in the dirty tree as clean. */
	makeclean(T, T->root_dirty);

	/*
	 * Make sure no callbacks are pending on the shadow tree before we
	 * garbage collect it.
	 */
	if (!events_immediate_register(callback_unshadow, WC, 1))
		goto err1;

	/* Success! */
	return (0);

err1:
	free(WC);

	/* Failure! */
	return (-1);
}