/* 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); }
/* 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); }
/* 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); }