|
|
|
@ -53,8 +53,6 @@ |
|
|
|
|
typedef struct fd_node { |
|
|
|
|
/** the owner of this fd node */ |
|
|
|
|
grpc_ares_ev_driver *ev_driver; |
|
|
|
|
/** refcount of the node */ |
|
|
|
|
gpr_refcount refs; |
|
|
|
|
/** the grpc_fd owned by this fd node */ |
|
|
|
|
grpc_fd *grpc_fd; |
|
|
|
|
/** a closure wrapping on_readable_cb, which should be invoked when the
|
|
|
|
@ -79,6 +77,8 @@ struct grpc_ares_ev_driver { |
|
|
|
|
ares_channel channel; |
|
|
|
|
/** pollset set for driving the IO events of the channel */ |
|
|
|
|
grpc_pollset_set *pollset_set; |
|
|
|
|
/** refcount of the event driver */ |
|
|
|
|
gpr_refcount refs; |
|
|
|
|
|
|
|
|
|
/** mutex guarding the rest of the state */ |
|
|
|
|
gpr_mu mu; |
|
|
|
@ -91,27 +91,36 @@ struct grpc_ares_ev_driver { |
|
|
|
|
static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_ares_ev_driver *ev_driver); |
|
|
|
|
|
|
|
|
|
static fd_node *fd_node_ref(fd_node *fdn) { |
|
|
|
|
gpr_log(GPR_DEBUG, "ref %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); |
|
|
|
|
gpr_ref(&fdn->refs); |
|
|
|
|
return fdn; |
|
|
|
|
static grpc_ares_ev_driver *grpc_ares_ev_driver_ref( |
|
|
|
|
grpc_ares_ev_driver *ev_driver) { |
|
|
|
|
gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
|
|
|
|
gpr_ref(&ev_driver->refs); |
|
|
|
|
return ev_driver; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void fd_node_unref(grpc_exec_ctx *exec_ctx, fd_node *fdn) { |
|
|
|
|
gpr_log(GPR_DEBUG, "unref %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); |
|
|
|
|
if (gpr_unref(&fdn->refs)) { |
|
|
|
|
gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); |
|
|
|
|
GPR_ASSERT(!fdn->readable_registered); |
|
|
|
|
GPR_ASSERT(!fdn->writable_registered); |
|
|
|
|
gpr_mu_destroy(&fdn->mu); |
|
|
|
|
grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, |
|
|
|
|
fdn->grpc_fd); |
|
|
|
|
grpc_fd_shutdown(exec_ctx, fdn->grpc_fd); |
|
|
|
|
grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, "c-ares query finished"); |
|
|
|
|
gpr_free(fdn); |
|
|
|
|
static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver *ev_driver) { |
|
|
|
|
gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
|
|
|
|
if (gpr_unref(&ev_driver->refs)) { |
|
|
|
|
gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
|
|
|
|
GPR_ASSERT(ev_driver->fds == NULL); |
|
|
|
|
gpr_mu_destroy(&ev_driver->mu); |
|
|
|
|
ares_destroy(ev_driver->channel); |
|
|
|
|
gpr_free(ev_driver); |
|
|
|
|
grpc_ares_cleanup(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) { |
|
|
|
|
gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); |
|
|
|
|
GPR_ASSERT(!fdn->readable_registered); |
|
|
|
|
GPR_ASSERT(!fdn->writable_registered); |
|
|
|
|
gpr_mu_destroy(&fdn->mu); |
|
|
|
|
grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, fdn->grpc_fd); |
|
|
|
|
grpc_fd_shutdown(exec_ctx, fdn->grpc_fd); |
|
|
|
|
grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, "c-ares query finished"); |
|
|
|
|
gpr_free(fdn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, |
|
|
|
|
grpc_pollset_set *pollset_set) { |
|
|
|
|
int status; |
|
|
|
@ -121,7 +130,7 @@ grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, |
|
|
|
|
} |
|
|
|
|
*ev_driver = gpr_malloc(sizeof(grpc_ares_ev_driver)); |
|
|
|
|
status = ares_init(&(*ev_driver)->channel); |
|
|
|
|
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create\n"); |
|
|
|
|
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create"); |
|
|
|
|
if (status != ARES_SUCCESS) { |
|
|
|
|
char *err_msg; |
|
|
|
|
gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", |
|
|
|
@ -132,25 +141,13 @@ grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, |
|
|
|
|
return err; |
|
|
|
|
} |
|
|
|
|
gpr_mu_init(&(*ev_driver)->mu); |
|
|
|
|
gpr_ref_init(&(*ev_driver)->refs, 1); |
|
|
|
|
(*ev_driver)->pollset_set = pollset_set; |
|
|
|
|
(*ev_driver)->fds = NULL; |
|
|
|
|
(*ev_driver)->working = false; |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void grpc_ares_ev_driver_cleanup(grpc_exec_ctx *exec_ctx, void *arg, |
|
|
|
|
grpc_error *error) { |
|
|
|
|
GPR_ASSERT(error == GRPC_ERROR_NONE); |
|
|
|
|
grpc_ares_ev_driver *ev_driver = arg; |
|
|
|
|
GPR_ASSERT(ev_driver->fds == NULL); |
|
|
|
|
gpr_mu_lock(&ev_driver->mu); |
|
|
|
|
gpr_mu_unlock(&ev_driver->mu); |
|
|
|
|
gpr_mu_destroy(&ev_driver->mu); |
|
|
|
|
ares_destroy(ev_driver->channel); |
|
|
|
|
gpr_free(ev_driver); |
|
|
|
|
grpc_ares_cleanup(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_ares_ev_driver_destroy(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_ares_ev_driver *ev_driver) { |
|
|
|
|
// Shutdown all the working fds, invoke their registered on_readable_cb and
|
|
|
|
@ -162,11 +159,7 @@ void grpc_ares_ev_driver_destroy(grpc_exec_ctx *exec_ctx, |
|
|
|
|
fdn = fdn->next; |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&ev_driver->mu); |
|
|
|
|
// Schedule the actual cleanup with exec_ctx, so that it happens after the
|
|
|
|
|
// fd shutdown process.
|
|
|
|
|
grpc_exec_ctx_sched( |
|
|
|
|
exec_ctx, grpc_closure_create(grpc_ares_ev_driver_cleanup, ev_driver), |
|
|
|
|
GRPC_ERROR_NONE, NULL); |
|
|
|
|
grpc_ares_ev_driver_unref(ev_driver); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Search fd in the fd_node list head. This is an O(n) search, the max possible
|
|
|
|
@ -208,10 +201,10 @@ static void on_readable_cb(grpc_exec_ctx *exec_ctx, void *arg, |
|
|
|
|
// grpc_ares_notify_on_event_locked().
|
|
|
|
|
ares_cancel(ev_driver->channel); |
|
|
|
|
} |
|
|
|
|
fd_node_unref(exec_ctx, fdn); |
|
|
|
|
gpr_mu_lock(&ev_driver->mu); |
|
|
|
|
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); |
|
|
|
|
gpr_mu_unlock(&ev_driver->mu); |
|
|
|
|
grpc_ares_ev_driver_unref(ev_driver); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void on_writable_cb(grpc_exec_ctx *exec_ctx, void *arg, |
|
|
|
@ -235,10 +228,10 @@ static void on_writable_cb(grpc_exec_ctx *exec_ctx, void *arg, |
|
|
|
|
// grpc_ares_notify_on_event_locked().
|
|
|
|
|
ares_cancel(ev_driver->channel); |
|
|
|
|
} |
|
|
|
|
fd_node_unref(exec_ctx, fdn); |
|
|
|
|
gpr_mu_lock(&ev_driver->mu); |
|
|
|
|
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); |
|
|
|
|
gpr_mu_unlock(&ev_driver->mu); |
|
|
|
|
grpc_ares_ev_driver_unref(ev_driver); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver) { |
|
|
|
@ -268,7 +261,6 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
|
|
|
|
fdn->readable_registered = false; |
|
|
|
|
fdn->writable_registered = false; |
|
|
|
|
gpr_mu_init(&fdn->mu); |
|
|
|
|
gpr_ref_init(&fdn->refs, 1); |
|
|
|
|
grpc_closure_init(&fdn->read_closure, on_readable_cb, fdn); |
|
|
|
|
grpc_closure_init(&fdn->write_closure, on_writable_cb, fdn); |
|
|
|
|
grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, fdn->grpc_fd); |
|
|
|
@ -281,7 +273,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
|
|
|
|
// not been registered with this socket.
|
|
|
|
|
if (ARES_GETSOCK_READABLE(socks_bitmask, i) && |
|
|
|
|
!fdn->readable_registered) { |
|
|
|
|
fd_node_ref(fdn); |
|
|
|
|
grpc_ares_ev_driver_ref(ev_driver); |
|
|
|
|
gpr_log(GPR_DEBUG, "notify read on: %d", |
|
|
|
|
grpc_fd_wrapped_fd(fdn->grpc_fd)); |
|
|
|
|
grpc_fd_notify_on_read(exec_ctx, fdn->grpc_fd, &fdn->read_closure); |
|
|
|
@ -293,7 +285,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
|
|
|
|
!fdn->writable_registered) { |
|
|
|
|
gpr_log(GPR_DEBUG, "notify write on: %d", |
|
|
|
|
grpc_fd_wrapped_fd(fdn->grpc_fd)); |
|
|
|
|
fd_node_ref(fdn); |
|
|
|
|
grpc_ares_ev_driver_ref(ev_driver); |
|
|
|
|
grpc_fd_notify_on_write(exec_ctx, fdn->grpc_fd, &fdn->write_closure); |
|
|
|
|
fdn->writable_registered = true; |
|
|
|
|
} |
|
|
|
@ -307,7 +299,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
|
|
|
|
fd_node *cur = ev_driver->fds; |
|
|
|
|
ev_driver->fds = ev_driver->fds->next; |
|
|
|
|
grpc_fd_shutdown(exec_ctx, cur->grpc_fd); |
|
|
|
|
fd_node_unref(exec_ctx, cur); |
|
|
|
|
fd_node_destroy(exec_ctx, cur); |
|
|
|
|
} |
|
|
|
|
ev_driver->fds = new_list; |
|
|
|
|
// If the ev driver has no working fd, all the tasks are done.
|
|
|
|
|