#include "includes.h"
#include "db_wrap.h"
#include "lib/tdb/include/tdb.h"
-#include "lib/events/events.h"
+#include "lib/tevent/tevent.h"
#include "lib/util/dlinklist.h"
#include "system/network.h"
#include "system/filesys.h"
#include "system/wait.h"
-#include "../include/ctdb.h"
+#include "../include/ctdb_client.h"
#include "../include/ctdb_private.h"
#include <sys/socket.h>
client->ctdb->statistics.client_packets_sent++;
if (hdr->operation == CTDB_REQ_MESSAGE) {
if (ctdb_queue_length(client->queue) > client->ctdb->tunable.max_queue_depth_drop_msg) {
- DEBUG(DEBUG_ERR,("Drop CTDB_REQ_MESSAGE to client. Queue full.\n"));
- return 0;
+ DEBUG(DEBUG_ERR,("CTDB_REQ_MESSAGE queue full - killing client connection.\n"));
+ talloc_free(client);
+ return -1;
}
}
return ctdb_queue_send(client->queue, (uint8_t *)hdr, hdr->length);
memcpy(&r->data[0], dstate->call->reply_data.dptr, r->datalen);
res = daemon_queue_send(client, &r->hdr);
+ if (res == -1) {
+ /* client is dead - return immediately */
+ return;
+ }
if (res != 0) {
DEBUG(DEBUG_ERR, (__location__ " Failed to queue packet from daemon to client\n"));
}
dstate = talloc(client, struct daemon_call_state);
if (dstate == NULL) {
- ctdb_ltdb_unlock(ctdb_db, key);
+ ret = ctdb_ltdb_unlock(ctdb_db, key);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " ctdb_ltdb_unlock() failed with error %d\n", ret));
+ }
+
DEBUG(DEBUG_ERR,(__location__ " Unable to allocate dstate\n"));
if (client->ctdb->statistics.pending_calls > 0) {
ctdb->statistics.pending_calls--;
call = dstate->call = talloc_zero(dstate, struct ctdb_call);
if (call == NULL) {
- ctdb_ltdb_unlock(ctdb_db, key);
+ ret = ctdb_ltdb_unlock(ctdb_db, key);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " ctdb_ltdb_unlock() failed with error %d\n", ret));
+ }
+
DEBUG(DEBUG_ERR,(__location__ " Unable to allocate call\n"));
if (client->ctdb->statistics.pending_calls > 0) {
ctdb->statistics.pending_calls--;
state = ctdb_daemon_call_send_remote(ctdb_db, call, &header);
}
- ctdb_ltdb_unlock(ctdb_db, key);
+ ret = ctdb_ltdb_unlock(ctdb_db, key);
+ if (ret != 0) {
+ DEBUG(DEBUG_ERR,(__location__ " ctdb_ltdb_unlock() failed with error %d\n", ret));
+ }
if (state == NULL) {
DEBUG(DEBUG_ERR,(__location__ " Unable to setup call send\n"));
DLIST_ADD(ctdb->client_pids, client_pid);
client->queue = ctdb_queue_setup(ctdb, client, fd, CTDB_DS_ALIGNMENT,
- ctdb_daemon_read_cb, client);
+ ctdb_daemon_read_cb, client,
+ "client-%u", client->pid);
talloc_set_destructor(client, ctdb_client_destructor);
talloc_set_destructor(client_pid, ctdb_clientpid_destructor);
}
}
+static void ctdb_setup_event_callback(struct ctdb_context *ctdb, int status,
+ void *private_data)
+{
+ if (status != 0) {
+ ctdb_fatal(ctdb, "Failed to run setup event\n");
+ return;
+ }
+ ctdb_run_notification_script(ctdb, "setup");
+
+ /* tell all other nodes we've just started up */
+ ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_ALL,
+ 0, CTDB_CONTROL_STARTUP, 0,
+ CTDB_CTRL_FLAG_NOREPLY,
+ tdb_null, NULL, NULL);
+}
+
/*
start the protocol going as a daemon
*/
}
ctdb->ev = event_context_init(NULL);
+ tevent_loop_allow_nesting(ctdb->ev);
ctdb_set_child_logging(ctdb);
ctdb_fatal(ctdb, "Failed to attach to databases\n");
}
- /* start frozen, then let the first election sort things out */
- if (ctdb_blocking_freeze(ctdb)) {
- ctdb_fatal(ctdb, "Failed to get initial freeze\n");
- }
-
ret = ctdb_event_script(ctdb, CTDB_EVENT_INIT);
if (ret != 0) {
ctdb_fatal(ctdb, "Failed to run init event\n");
}
ctdb_run_notification_script(ctdb, "init");
+ /* start frozen, then let the first election sort things out */
+ if (ctdb_blocking_freeze(ctdb)) {
+ ctdb_fatal(ctdb, "Failed to get initial freeze\n");
+ }
+
/* now start accepting clients, only can do this once frozen */
fde = event_add_fd(ctdb->ev, ctdb, ctdb->daemon.sd,
- EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
+ EVENT_FD_READ,
ctdb_accept_client, ctdb);
-
- /* tell all other nodes we've just started up */
- ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_ALL,
- 0, CTDB_CONTROL_STARTUP, 0,
- CTDB_CTRL_FLAG_NOREPLY,
- tdb_null, NULL, NULL);
+ tevent_fd_set_auto_close(fde);
/* release any IPs we hold from previous runs of the daemon */
ctdb_release_all_ips(ctdb);
exit(1);
}
+ ret = ctdb_event_script_callback(ctdb,
+ ctdb,
+ ctdb_setup_event_callback,
+ ctdb,
+ false,
+ CTDB_EVENT_SETUP,
+ "");
+ if (ret != 0) {
+ DEBUG(DEBUG_CRIT,("Failed to set up 'setup' event\n"));
+ exit(1);
+ }
+
if (use_syslog) {
if (start_syslog_daemon(ctdb)) {
DEBUG(DEBUG_CRIT, ("Failed to start syslog daemon\n"));
struct ctdb_client *client = state->client;
struct ctdb_reply_control *r;
size_t len;
+ int ret;
/* construct a message to send to the client containing the data */
len = offsetof(struct ctdb_reply_control, data) + data.dsize;
memcpy(&r->data[r->datalen], errormsg, r->errorlen);
}
- daemon_queue_send(client, &r->hdr);
-
- talloc_free(state);
+ ret = daemon_queue_send(client, &r->hdr);
+ if (ret != -1) {
+ talloc_free(state);
+ }
}
/*
struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
struct ctdb_client_notify_list *nl;
- DEBUG(DEBUG_ERR,("Register srvid %llu for client %d\n", (unsigned long long)notify->srvid, client_id));
+ DEBUG(DEBUG_INFO,("Register srvid %llu for client %d\n", (unsigned long long)notify->srvid, client_id));
if (indata.dsize < offsetof(struct ctdb_client_notify_register, notify_data)) {
DEBUG(DEBUG_ERR,(__location__ " Too little data in control : %d\n", (int)indata.dsize));
struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
struct ctdb_client_notify_list *nl;
- DEBUG(DEBUG_ERR,("Deregister srvid %llu for client %d\n", (unsigned long long)notify->srvid, client_id));
+ DEBUG(DEBUG_INFO,("Deregister srvid %llu for client %d\n", (unsigned long long)notify->srvid, client_id));
if (client == NULL) {
DEBUG(DEBUG_ERR,(__location__ " Could not find client parent structure. You can not send this control to a remote node\n"));