static void lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) { ns_lwdclientmgr_t *cm = ev->ev_arg; ns_lwdclient_t *client; REQUIRE(!SHUTTINGDOWN(cm)); ns_lwdclient_log(50, "got shutdown event, task %p, lwdclientmgr %p", task, cm); /* * run through the idle list and free the clients there. Idle * clients do not have a recv running nor do they have any finds * or similar running. */ LOCK(&cm->lock); client = ISC_LIST_HEAD(cm->idle); while (client != NULL) { ns_lwdclient_log(50, "destroying client %p, manager %p", client, cm); ISC_LIST_UNLINK(cm->idle, client, link); isc_mem_put(cm->mctx, client, sizeof(*client)); client = ISC_LIST_HEAD(cm->idle); } UNLOCK(&cm->lock); /* * Cancel any pending I/O. */ isc_socket_cancel(cm->sock, task, ISC_SOCKCANCEL_ALL); /* * Run through the running client list and kill off any finds * in progress. */ LOCK(&cm->lock); client = ISC_LIST_HEAD(cm->running); while (client != NULL) { if (client->find != client->v4find && client->find != client->v6find) dns_adb_cancelfind(client->find); if (client->v4find != NULL) dns_adb_cancelfind(client->v4find); if (client->v6find != NULL) dns_adb_cancelfind(client->v6find); client = ISC_LIST_NEXT(client, link); } cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN; UNLOCK(&cm->lock); isc_event_free(&ev); }
/* * This function will start a new recv() on a socket for this client manager. */ isc_result_t ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) { ns_lwdclient_t *client; isc_result_t result; isc_region_t r; if (SHUTTINGDOWN(cm)) { lwdclientmgr_destroy(cm); return (ISC_R_SUCCESS); } /* * If a recv is already running, don't bother. */ if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) return (ISC_R_SUCCESS); /* * If we have no idle slots, just return success. */ client = ISC_LIST_HEAD(cm->idle); if (client == NULL) return (ISC_R_SUCCESS); INSIST(NS_LWDCLIENT_ISIDLE(client)); /* * Issue the recv. If it fails, return that it did. */ r.base = client->buffer; r.length = LWRES_RECVLENGTH; result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv, client); if (result != ISC_R_SUCCESS) return (result); /* * Set the flag to say we've issued a recv() call. */ cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING; /* * Remove the client from the idle list, and put it on the running * list. */ NS_LWDCLIENT_SETRECV(client); ISC_LIST_UNLINK(cm->idle, client, link); ISC_LIST_APPEND(cm->running, client, link); return (ISC_R_SUCCESS); }
static void lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) { ns_lwdclient_t *client; ns_lwreslistener_t *listener; LOCK(&cm->lock); if (!SHUTTINGDOWN(cm)) { UNLOCK(&cm->lock); return; } /* * Run through the idle list and free the clients there. Idle * clients do not have a recv running nor do they have any finds * or similar running. */ client = ISC_LIST_HEAD(cm->idle); while (client != NULL) { ns_lwdclient_log(50, "destroying client %p, manager %p", client, cm); ISC_LIST_UNLINK(cm->idle, client, link); isc_mem_put(cm->mctx, client, sizeof(*client)); client = ISC_LIST_HEAD(cm->idle); } if (!ISC_LIST_EMPTY(cm->running)) { UNLOCK(&cm->lock); return; } UNLOCK(&cm->lock); lwres_context_destroy(&cm->lwctx); cm->view = NULL; isc_socket_detach(&cm->sock); isc_task_detach(&cm->task); DESTROYLOCK(&cm->lock); listener = cm->listener; ns_lwreslistener_unlinkcm(listener, cm); ns_lwdclient_log(50, "destroying manager %p", cm); isc_mem_put(cm->mctx, cm, sizeof(*cm)); ns_lwreslistener_detach(&listener); }
/* * This function will start a new recv() on a socket for this client manager. */ isc_result_t ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) { ns_lwdclient_t *client; isc_result_t result; isc_region_t r; isc_boolean_t destroy = ISC_FALSE; LOCK(&cm->lock); if (SHUTTINGDOWN(cm)) { destroy = ISC_TRUE; result = ISC_R_SUCCESS; goto unlock; } /* * If a recv is already running, don't bother. */ if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) { result = ISC_R_SUCCESS; goto unlock; } /* * If we have no idle slots, just return success. */ client = ISC_LIST_HEAD(cm->idle); if (client == NULL) { result = ISC_R_SUCCESS; goto unlock; } INSIST(NS_LWDCLIENT_ISIDLE(client)); /* * Set the flag to say there is a recv pending. If isc_socket_recv * fails we will clear the flag otherwise it will be cleared by * ns_lwdclient_recv. */ cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING; /* * Issue the recv. If it fails, return that it did. */ r.base = client->buffer; r.length = LWRES_RECVLENGTH; result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv, client); if (result != ISC_R_SUCCESS) { cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING; goto unlock; } /* * Remove the client from the idle list, and put it on the running * list. */ NS_LWDCLIENT_SETRECV(client); ISC_LIST_UNLINK(cm->idle, client, link); ISC_LIST_APPEND(cm->running, client, link); unlock: UNLOCK(&cm->lock); if (destroy) lwdclientmgr_destroy(cm); return (result); }