/* setup a packet queue on a socket */ struct ctdb_queue *ctdb_queue_setup(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, int fd, int alignment, ctdb_queue_cb_fn_t callback, void *private_data, const char *fmt, ...) { struct ctdb_queue *queue; va_list ap; queue = talloc_zero(mem_ctx, struct ctdb_queue); CTDB_NO_MEMORY_NULL(ctdb, queue); va_start(ap, fmt); queue->name = talloc_vasprintf(mem_ctx, fmt, ap); va_end(ap); CTDB_NO_MEMORY_NULL(ctdb, queue->name); queue->im= tevent_create_immediate(queue); CTDB_NO_MEMORY_NULL(ctdb, queue->im); queue->ctdb = ctdb; queue->fd = fd; queue->alignment = alignment; queue->private_data = private_data; queue->callback = callback; if (fd != -1) { if (ctdb_queue_set_fd(queue, fd) != 0) { talloc_free(queue); return NULL; } } talloc_set_destructor(queue, queue_destructor); return queue; }
/* stop any connecting (established or pending) to a node */ void ctdb_tcp_stop_connection(struct ctdb_node *node) { struct ctdb_tcp_node *tnode = talloc_get_type( node->private_data, struct ctdb_tcp_node); ctdb_queue_set_fd(tnode->out_queue, -1); talloc_free(tnode->connect_te); talloc_free(tnode->connect_fde); tnode->connect_fde = NULL; tnode->connect_te = NULL; if (tnode->fd != -1) { close(tnode->fd); tnode->fd = -1; } }
/* called when socket becomes writeable on connect */ static void ctdb_node_connect_write(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct ctdb_node *node = talloc_get_type(private_data, struct ctdb_node); struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data, struct ctdb_tcp_node); struct ctdb_context *ctdb = node->ctdb; int error = 0; socklen_t len = sizeof(error); int one = 1; talloc_free(tnode->connect_te); tnode->connect_te = NULL; if (getsockopt(tnode->fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0 || error != 0) { ctdb_tcp_stop_connection(node); tnode->connect_te = tevent_add_timer(ctdb->ev, tnode, timeval_current_ofs(1, 0), ctdb_tcp_node_connect, node); return; } talloc_free(tnode->connect_fde); tnode->connect_fde = NULL; if (setsockopt(tnode->fd,IPPROTO_TCP,TCP_NODELAY,(char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set TCP_NODELAY on fd - %s\n", strerror(errno))); } if (setsockopt(tnode->fd,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set KEEPALIVE on fd - %s\n", strerror(errno))); } ctdb_queue_set_fd(tnode->out_queue, tnode->fd); /* the queue subsystem now owns this fd */ tnode->fd = -1; }
/* setup a packet queue on a socket */ struct ctdb_queue *ctdb_queue_setup(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, int fd, int alignment, ctdb_queue_cb_fn_t callback, void *private_data, const char *fmt, ...) { struct ctdb_queue *queue; va_list ap; queue = talloc_zero(mem_ctx, struct ctdb_queue); CTDB_NO_MEMORY_NULL(ctdb, queue); va_start(ap, fmt); queue->name = talloc_vasprintf(mem_ctx, fmt, ap); va_end(ap); CTDB_NO_MEMORY_NULL(ctdb, queue->name); queue->im= tevent_create_immediate(queue); CTDB_NO_MEMORY_NULL(ctdb, queue->im); queue->ctdb = ctdb; queue->fd = fd; queue->alignment = alignment; queue->private_data = private_data; queue->callback = callback; if (fd != -1) { if (ctdb_queue_set_fd(queue, fd) != 0) { talloc_free(queue); return NULL; } } talloc_set_destructor(queue, queue_destructor); queue->buffer_size = ctdb->tunable.queue_buffer_size; /* In client code, ctdb->tunable is not initialized. * This does not affect recovery daemon. */ if (queue->buffer_size == 0) { queue->buffer_size = 1024; } return queue; }