/* called by the transport layer when a packet comes in */ static void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t length) { struct ctdb_req_header *hdr = (struct ctdb_req_header *)data; CTDB_INCREMENT_STAT(ctdb, node_packets_recv); /* up the counter for this source node, so we know its alive */ if (ctdb_validate_pnn(ctdb, hdr->srcnode)) { /* as a special case, redirected calls don't increment the rx_cnt */ if (hdr->operation != CTDB_REQ_CALL || ((struct ctdb_req_call_old *)hdr)->hopcount == 0) { ctdb->nodes[hdr->srcnode]->rx_cnt++; } } ctdb_input_pkt(ctdb, hdr); }
/* send a control message to a node */ int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid, uint32_t opcode, uint32_t client_id, uint32_t flags, TDB_DATA data, ctdb_control_callback_fn_t callback, void *private_data) { struct ctdb_req_control_old *c; struct ctdb_control_state *state; size_t len; if (ctdb->methods == NULL) { DEBUG(DEBUG_INFO,(__location__ " Failed to send control. Transport is DOWN\n")); return -1; } if (((destnode == CTDB_BROADCAST_VNNMAP) || (destnode == CTDB_BROADCAST_ALL) || (destnode == CTDB_BROADCAST_CONNECTED)) && !(flags & CTDB_CTRL_FLAG_NOREPLY)) { DEBUG(DEBUG_CRIT,("Attempt to broadcast control without NOREPLY\n")); return -1; } if (destnode != CTDB_BROADCAST_VNNMAP && destnode != CTDB_BROADCAST_ALL && destnode != CTDB_BROADCAST_CONNECTED && (!ctdb_validate_pnn(ctdb, destnode) || (ctdb->nodes[destnode]->flags & NODE_FLAGS_DISCONNECTED))) { if (!(flags & CTDB_CTRL_FLAG_NOREPLY)) { callback(ctdb, -1, tdb_null, "ctdb_control to disconnected node", private_data); } return 0; } /* the state is made a child of private_data if possible. This means any reply will be discarded if the private_data goes away */ state = talloc(private_data?private_data:ctdb, struct ctdb_control_state); CTDB_NO_MEMORY(ctdb, state); state->reqid = reqid_new(ctdb->idr, state); state->callback = callback; state->private_data = private_data; state->ctdb = ctdb; state->flags = flags; talloc_set_destructor(state, ctdb_control_destructor); len = offsetof(struct ctdb_req_control_old, data) + data.dsize; c = ctdb_transport_allocate(ctdb, state, CTDB_REQ_CONTROL, len, struct ctdb_req_control_old); CTDB_NO_MEMORY(ctdb, c); talloc_set_name_const(c, "ctdb_req_control packet"); c->hdr.destnode = destnode; c->hdr.reqid = state->reqid; c->opcode = opcode; c->client_id = client_id; c->flags = flags; c->srvid = srvid; c->datalen = data.dsize; if (data.dsize) { memcpy(&c->data[0], data.dptr, data.dsize); } ctdb_queue_packet(ctdb, &c->hdr); if (flags & CTDB_CTRL_FLAG_NOREPLY) { talloc_free(state); return 0; } if (ctdb->tunable.control_timeout) { tevent_add_timer(ctdb->ev, state, timeval_current_ofs(ctdb->tunable.control_timeout, 0), ctdb_control_timeout, state); } talloc_free(c); return 0; }