/* 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; }
/* make a remote ctdb call - async send. Called in daemon context. This constructs a ctdb_call request and queues it for processing. This call never blocks. */ struct ctdb_call_state *ctdb_daemon_call_send_remote(struct ctdb_db_context *ctdb_db, struct ctdb_call *call, struct ctdb_ltdb_header *header) { uint32_t len; struct ctdb_call_state *state; struct ctdb_context *ctdb = ctdb_db->ctdb; state = talloc_zero(ctdb_db, struct ctdb_call_state); CTDB_NO_MEMORY_NULL(ctdb, state); len = offsetof(struct ctdb_req_call, data) + call->key.dsize + call->call_data.dsize; state->c = ctdb->methods->allocate_pkt(state, len); CTDB_NO_MEMORY_NULL(ctdb, state->c); talloc_set_name_const(state->c, "req_call packet"); state->c->hdr.length = len; state->c->hdr.ctdb_magic = CTDB_MAGIC; state->c->hdr.ctdb_version = CTDB_VERSION; state->c->hdr.operation = CTDB_REQ_CALL; state->c->hdr.destnode = header->dmaster; state->c->hdr.srcnode = ctdb->vnn; /* this limits us to 16k outstanding messages - not unreasonable */ state->c->hdr.reqid = idr_get_new(ctdb->idr, state, 0xFFFF); state->c->flags = call->flags; state->c->db_id = ctdb_db->db_id; state->c->callid = call->call_id; state->c->keylen = call->key.dsize; state->c->calldatalen = call->call_data.dsize; memcpy(&state->c->data[0], call->key.dptr, call->key.dsize); memcpy(&state->c->data[call->key.dsize], call->call_data.dptr, call->call_data.dsize); state->call = *call; state->call.call_data.dptr = &state->c->data[call->key.dsize]; state->call.key.dptr = &state->c->data[0]; state->node = ctdb->nodes[header->dmaster]; state->state = CTDB_CALL_WAIT; state->header = *header; state->ctdb_db = ctdb_db; talloc_set_destructor(state, ctdb_call_destructor); ctdb_queue_packet(ctdb, &state->c->hdr); event_add_timed(ctdb->ev, state, timeval_current_ofs(CTDB_REQ_TIMEOUT, 0), ctdb_call_timeout, state); return state; }
/* construct an event driven local ctdb_call this is used so that locally processed ctdb_call requests are processed in an event driven manner */ struct ctdb_call_state *ctdb_call_local_send(struct ctdb_db_context *ctdb_db, struct ctdb_call *call, struct ctdb_ltdb_header *header, TDB_DATA *data) { struct ctdb_call_state *state; struct ctdb_context *ctdb = ctdb_db->ctdb; int ret; state = talloc_zero(ctdb_db, struct ctdb_call_state); CTDB_NO_MEMORY_NULL(ctdb, state); talloc_steal(state, data->dptr); state->state = CTDB_CALL_DONE; state->node = ctdb->nodes[ctdb->vnn]; state->call = *call; state->ctdb_db = ctdb_db; ret = ctdb_call_local(ctdb_db, &state->call, header, data, ctdb->vnn); talloc_steal(state, state->call.reply_data.dptr); event_add_timed(ctdb->ev, state, timeval_zero(), call_local_trigger, state); return state; }
/* 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; }