2 Fake CTDB server for testing
4 Copyright (C) Amitay Isaacs 2016
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/network.h"
22 #include "system/time.h"
29 #include "lib/util/dlinklist.h"
30 #include "lib/util/tevent_unix.h"
31 #include "lib/util/debug.h"
32 #include "lib/util/samba_util.h"
33 #include "lib/async_req/async_sock.h"
35 #include "protocol/protocol.h"
36 #include "protocol/protocol_api.h"
37 #include "protocol/protocol_util.h"
39 #include "common/comm.h"
40 #include "common/logging.h"
41 #include "common/tunable.h"
42 #include "common/srvid.h"
44 #include "ipalloc_read_known_ips.h"
47 #define CTDB_PORT 4379
49 /* A fake flag that is only supported by some functions */
50 #define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
56 uint32_t capabilities;
57 bool recovery_disabled;
58 void *recovery_substate;
74 struct interface_map {
76 struct interface *iface;
98 struct fake_control_failure {
99 struct fake_control_failure *prev, *next;
100 enum ctdb_controls opcode;
107 struct ctdb_client *prev, *next;
108 struct ctdbd_context *ctdb;
113 struct ctdbd_context {
114 struct node_map *node_map;
115 struct interface_map *iface_map;
116 struct vnn_map *vnn_map;
117 struct database_map *db_map;
118 struct srvid_context *srv;
120 struct timeval start_time;
121 struct timeval recovery_start_time;
122 struct timeval recovery_end_time;
123 bool takeover_disabled;
125 enum ctdb_runstate runstate;
126 struct ctdb_tunable_list tun_list;
128 struct ctdb_public_ip_list *known_ips;
129 struct fake_control_failure *control_failures;
130 struct ctdb_client *client_list;
137 static struct node_map *nodemap_init(TALLOC_CTX *mem_ctx)
139 struct node_map *node_map;
141 node_map = talloc_zero(mem_ctx, struct node_map);
142 if (node_map == NULL) {
146 node_map->pnn = CTDB_UNKNOWN_PNN;
147 node_map->recmaster = CTDB_UNKNOWN_PNN;
152 /* Read a nodemap from stdin. Each line looks like:
153 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
154 * EOF or a blank line terminates input.
156 * By default, capablities for each node are
157 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER. These 2
158 * capabilities can be faked off by adding, for example,
159 * -CTDB_CAP_RECMASTER.
162 static bool nodemap_parse(struct node_map *node_map)
166 while ((fgets(line, sizeof(line), stdin) != NULL)) {
167 uint32_t pnn, flags, capabilities;
170 ctdb_sock_addr saddr;
174 if (line[0] == '\n') {
178 /* Get rid of pesky newline */
179 if ((t = strchr(line, '\n')) != NULL) {
184 tok = strtok(line, " \t");
186 fprintf(stderr, "bad line (%s) - missing PNN\n", line);
189 pnn = (uint32_t)strtoul(tok, NULL, 0);
192 tok = strtok(NULL, " \t");
194 fprintf(stderr, "bad line (%s) - missing IP\n", line);
197 ret = ctdb_sock_addr_from_string(tok, &saddr, false);
199 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
202 ctdb_sock_addr_set_port(&saddr, CTDB_PORT);
203 ip = talloc_strdup(node_map, tok);
209 tok = strtok(NULL, " \t");
211 fprintf(stderr, "bad line (%s) - missing flags\n",
215 flags = (uint32_t)strtoul(tok, NULL, 0);
216 /* Handle deleted nodes */
217 if (flags & NODE_FLAGS_DELETED) {
219 ip = talloc_strdup(node_map, "0.0.0.0");
224 capabilities = CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER;
226 tok = strtok(NULL, " \t");
227 while (tok != NULL) {
228 if (strcmp(tok, "CURRENT") == 0) {
230 } else if (strcmp(tok, "RECMASTER") == 0) {
231 node_map->recmaster = pnn;
232 } else if (strcmp(tok, "-CTDB_CAP_RECMASTER") == 0) {
233 capabilities &= ~CTDB_CAP_RECMASTER;
234 } else if (strcmp(tok, "-CTDB_CAP_LMASTER") == 0) {
235 capabilities &= ~CTDB_CAP_LMASTER;
236 } else if (strcmp(tok, "TIMEOUT") == 0) {
237 /* This can be done with just a flag
238 * value but it is probably clearer
239 * and less error-prone to fake this
240 * with an explicit token */
241 flags |= NODE_FLAGS_FAKE_TIMEOUT;
243 tok = strtok(NULL, " \t");
246 node_map->node = talloc_realloc(node_map, node_map->node,
248 node_map->num_nodes + 1);
249 if (node_map->node == NULL) {
252 node = &node_map->node[node_map->num_nodes];
254 ret = ctdb_sock_addr_from_string(ip, &node->addr, false);
256 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
259 ctdb_sock_addr_set_port(&node->addr, CTDB_PORT);
262 node->capabilities = capabilities;
263 node->recovery_disabled = false;
264 node->recovery_substate = NULL;
266 node_map->num_nodes += 1;
269 DEBUG(DEBUG_INFO, ("Parsing nodemap done\n"));
273 DEBUG(DEBUG_INFO, ("Parsing nodemap failed\n"));
278 /* Append a node to a node map with given address and flags */
279 static bool node_map_add(struct ctdb_node_map *nodemap,
280 const char *nstr, uint32_t flags)
284 struct ctdb_node_and_flags *n;
287 ret = ctdb_sock_addr_from_string(nstr, &addr, false);
289 fprintf(stderr, "Invalid IP address %s\n", nstr);
292 ctdb_sock_addr_set_port(&addr, CTDB_PORT);
295 nodemap->node = talloc_realloc(nodemap, nodemap->node,
296 struct ctdb_node_and_flags, num+1);
297 if (nodemap->node == NULL) {
301 n = &nodemap->node[num];
306 nodemap->num = num+1;
310 /* Read a nodes file into a node map */
311 static struct ctdb_node_map *ctdb_read_nodes_file(TALLOC_CTX *mem_ctx,
317 struct ctdb_node_map *nodemap;
319 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
320 if (nodemap == NULL) {
324 lines = file_lines_load(nlist, &nlines, 0, mem_ctx);
329 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
333 for (i=0; i<nlines; i++) {
339 /* strip leading spaces */
340 while((*node == ' ') || (*node == '\t')) {
346 /* strip trailing spaces */
348 ((node[len-1] == ' ') || (node[len-1] == '\t')))
358 /* A "deleted" node is a node that is
359 commented out in the nodes file. This is
360 used instead of removing a line, which
361 would cause subsequent nodes to change
363 flags = NODE_FLAGS_DELETED;
364 node = discard_const("0.0.0.0");
368 if (! node_map_add(nodemap, node, flags)) {
370 TALLOC_FREE(nodemap);
379 static struct ctdb_node_map *read_nodes_file(TALLOC_CTX *mem_ctx,
382 struct ctdb_node_map *nodemap;
383 char nodepath[PATH_MAX];
384 const char *nodes_list;
386 /* read the nodes file */
387 sprintf(nodepath, "CTDB_NODES_%u", pnn);
388 nodes_list = getenv(nodepath);
389 if (nodes_list == NULL) {
390 nodes_list = getenv("CTDB_NODES");
391 if (nodes_list == NULL) {
392 DEBUG(DEBUG_INFO, ("Nodes file not defined\n"));
397 nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
398 if (nodemap == NULL) {
399 DEBUG(DEBUG_INFO, ("Failed to read nodes file \"%s\"\n",
407 static struct interface_map *interfaces_init(TALLOC_CTX *mem_ctx)
409 struct interface_map *iface_map;
411 iface_map = talloc_zero(mem_ctx, struct interface_map);
412 if (iface_map == NULL) {
419 /* Read interfaces information. Same format as "ctdb ifaces -Y"
421 * :Name:LinkStatus:References:
426 static bool interfaces_parse(struct interface_map *iface_map)
430 while ((fgets(line, sizeof(line), stdin) != NULL)) {
433 char *tok, *t, *name;
434 struct interface *iface;
436 if (line[0] == '\n') {
440 /* Get rid of pesky newline */
441 if ((t = strchr(line, '\n')) != NULL) {
445 if (strcmp(line, ":Name:LinkStatus:References:") == 0) {
449 /* Leading colon... */
450 // tok = strtok(line, ":");
453 tok = strtok(line, ":");
455 fprintf(stderr, "bad line (%s) - missing name\n", line);
461 tok = strtok(NULL, ":");
463 fprintf(stderr, "bad line (%s) - missing link state\n",
467 link_state = (uint16_t)strtoul(tok, NULL, 0);
470 tok = strtok(NULL, ":");
472 fprintf(stderr, "bad line (%s) - missing references\n",
476 references = (uint32_t)strtoul(tok, NULL, 0);
478 iface_map->iface = talloc_realloc(iface_map, iface_map->iface,
481 if (iface_map->iface == NULL) {
485 iface = &iface_map->iface[iface_map->num];
487 iface->name = talloc_strdup(iface_map, name);
488 if (iface->name == NULL) {
491 iface->link_up = link_state;
492 iface->references = references;
497 DEBUG(DEBUG_INFO, ("Parsing interfaces done\n"));
501 fprintf(stderr, "Parsing interfaces failed\n");
505 static struct vnn_map *vnnmap_init(TALLOC_CTX *mem_ctx)
507 struct vnn_map *vnn_map;
509 vnn_map = talloc_zero(mem_ctx, struct vnn_map);
510 if (vnn_map == NULL) {
511 fprintf(stderr, "Memory error\n");
514 vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
515 vnn_map->generation = INVALID_GENERATION;
528 static bool vnnmap_parse(struct vnn_map *vnn_map)
532 while (fgets(line, sizeof(line), stdin) != NULL) {
536 if (line[0] == '\n') {
540 /* Get rid of pesky newline */
541 if ((t = strchr(line, '\n')) != NULL) {
545 n = (uint32_t) strtol(line, NULL, 0);
548 if (vnn_map->generation == INVALID_GENERATION) {
549 vnn_map->generation = n;
553 vnn_map->map = talloc_realloc(vnn_map, vnn_map->map, uint32_t,
555 if (vnn_map->map == NULL) {
556 fprintf(stderr, "Memory error\n");
560 vnn_map->map[vnn_map->size] = n;
564 DEBUG(DEBUG_INFO, ("Parsing vnnmap done\n"));
568 fprintf(stderr, "Parsing vnnmap failed\n");
572 static bool reclock_parse(struct ctdbd_context *ctdb)
577 if (fgets(line, sizeof(line), stdin) == NULL) {
581 if (line[0] == '\n') {
582 /* Recovery lock remains unset */
586 /* Get rid of pesky newline */
587 if ((t = strchr(line, '\n')) != NULL) {
591 ctdb->reclock = talloc_strdup(ctdb, line);
592 if (ctdb->reclock == NULL) {
596 /* Swallow possible blank line following section. Picky
597 * compiler settings don't allow the return value to be
598 * ignored, so make the compiler happy.
600 if (fgets(line, sizeof(line), stdin) == NULL) {
603 DEBUG(DEBUG_INFO, ("Parsing reclock done\n"));
607 fprintf(stderr, "Parsing reclock failed\n");
611 static struct database_map *dbmap_init(TALLOC_CTX *mem_ctx)
613 struct database_map *db_map;
615 db_map = talloc_zero(mem_ctx, struct database_map);
616 if (db_map == NULL) {
623 /* Read a database map from stdin. Each line looks like:
624 * <ID> <NAME> [FLAGS] [SEQ_NUM]
625 * EOF or a blank line terminates input.
627 * By default, flags and seq_num are 0
630 static bool dbmap_parse(struct database_map *db_map)
634 while ((fgets(line, sizeof(line), stdin) != NULL)) {
637 uint32_t seq_num = 0;
642 if (line[0] == '\n') {
646 /* Get rid of pesky newline */
647 if ((t = strchr(line, '\n')) != NULL) {
652 tok = strtok(line, " \t");
654 fprintf(stderr, "bad line (%s) - missing ID\n", line);
657 id = (uint32_t)strtoul(tok, NULL, 0);
660 tok = strtok(NULL, " \t");
662 fprintf(stderr, "bad line (%s) - missing NAME\n", line);
665 name = talloc_strdup(db_map, tok);
671 tok = strtok(NULL, " \t");
672 while (tok != NULL) {
673 if (strcmp(tok, "PERSISTENT") == 0) {
674 flags |= CTDB_DB_FLAGS_PERSISTENT;
675 } else if (strcmp(tok, "STICKY") == 0) {
676 flags |= CTDB_DB_FLAGS_STICKY;
677 } else if (strcmp(tok, "READONLY") == 0) {
678 flags |= CTDB_DB_FLAGS_READONLY;
679 } else if (strcmp(tok, "REPLICATED") == 0) {
680 flags |= CTDB_DB_FLAGS_REPLICATED;
681 } else if (tok[0] >= '0'&& tok[0] <= '9') {
682 uint8_t nv = CTDB_DB_FLAGS_PERSISTENT |
683 CTDB_DB_FLAGS_REPLICATED;
685 if ((flags & nv) == 0) {
687 "seq_num for volatile db\n");
690 seq_num = (uint64_t)strtoull(tok, NULL, 0);
693 tok = strtok(NULL, " \t");
696 db_map->db = talloc_realloc(db_map, db_map->db,
698 db_map->num_dbs + 1);
699 if (db_map->db == NULL) {
702 db = &db_map->db[db_map->num_dbs];
707 db->seq_num = seq_num;
709 db_map->num_dbs += 1;
712 DEBUG(DEBUG_INFO, ("Parsing dbmap done\n"));
716 DEBUG(DEBUG_INFO, ("Parsing dbmap failed\n"));
721 static struct database *database_find(struct database_map *map,
726 for (i = 0; i < map->num_dbs; i++) {
727 struct database *db = &map->db[i];
729 if (db->id == db_id) {
737 static bool public_ips_parse(struct ctdbd_context *ctdb,
741 D_ERR("Must initialise nodemap before public IPs\n");
745 ctdb->known_ips = ipalloc_read_known_ips(ctdb, numnodes, false);
747 return (ctdb->known_ips != NULL);
750 /* Read information about controls to fail. Format is:
751 * <opcode> <pnn> {ERROR|TIMEOUT} <comment>
753 static bool control_failures_parse(struct ctdbd_context *ctdb)
757 while ((fgets(line, sizeof(line), stdin) != NULL)) {
759 enum ctdb_controls opcode;
763 struct fake_control_failure *failure = NULL;
765 if (line[0] == '\n') {
769 /* Get rid of pesky newline */
770 if ((t = strchr(line, '\n')) != NULL) {
775 tok = strtok(line, " \t");
777 D_ERR("bad line (%s) - missing opcode\n", line);
780 opcode = (enum ctdb_controls)strtoul(tok, NULL, 0);
783 tok = strtok(NULL, " \t");
785 D_ERR("bad line (%s) - missing PNN\n", line);
788 pnn = (uint32_t)strtoul(tok, NULL, 0);
791 tok = strtok(NULL, " \t");
793 D_ERR("bad line (%s) - missing errno\n", line);
796 error = talloc_strdup(ctdb, tok);
800 if (strcmp(error, "ERROR") != 0 &&
801 strcmp(error, "TIMEOUT") != 0) {
802 D_ERR("bad line (%s) "
803 "- error must be \"ERROR\" or \"TIMEOUT\"\n",
809 tok = strtok(NULL, "\n"); /* rest of line */
811 D_ERR("bad line (%s) - missing comment\n", line);
814 comment = talloc_strdup(ctdb, tok);
815 if (comment == NULL) {
819 failure = talloc_zero(ctdb, struct fake_control_failure);
820 if (failure == NULL) {
824 failure->opcode = opcode;
826 failure->error = error;
827 failure->comment = comment;
829 DLIST_ADD(ctdb->control_failures, failure);
832 D_INFO("Parsing fake control failures done\n");
836 D_INFO("Parsing fake control failures failed\n");
844 static int ctdb_client_destructor(struct ctdb_client *client)
846 DLIST_REMOVE(client->ctdb->client_list, client);
850 static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
853 struct ctdb_client *client;
855 client = talloc_zero(client_state, struct ctdb_client);
856 if (client == NULL) {
861 client->pid = client_pid;
862 client->state = client_state;
864 DLIST_ADD(ctdb->client_list, client);
865 talloc_set_destructor(client, ctdb_client_destructor);
869 static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
871 struct ctdb_client *client;
873 for (client=ctdb->client_list; client != NULL; client=client->next) {
874 if (client->pid == client_pid) {
875 return client->state;
886 static uint32_t new_generation(uint32_t old_generation)
891 generation = random();
892 if (generation != INVALID_GENERATION &&
893 generation != old_generation) {
901 static struct ctdbd_context *ctdbd_setup(TALLOC_CTX *mem_ctx)
903 struct ctdbd_context *ctdb;
908 ctdb = talloc_zero(mem_ctx, struct ctdbd_context);
913 ctdb->node_map = nodemap_init(ctdb);
914 if (ctdb->node_map == NULL) {
918 ctdb->iface_map = interfaces_init(ctdb);
919 if (ctdb->iface_map == NULL) {
923 ctdb->vnn_map = vnnmap_init(ctdb);
924 if (ctdb->vnn_map == NULL) {
928 ctdb->db_map = dbmap_init(ctdb);
929 if (ctdb->db_map == NULL) {
933 ret = srvid_init(ctdb, &ctdb->srv);
938 while (fgets(line, sizeof(line), stdin) != NULL) {
941 if ((t = strchr(line, '\n')) != NULL) {
945 if (strcmp(line, "NODEMAP") == 0) {
946 status = nodemap_parse(ctdb->node_map);
947 } else if (strcmp(line, "IFACES") == 0) {
948 status = interfaces_parse(ctdb->iface_map);
949 } else if (strcmp(line, "VNNMAP") == 0) {
950 status = vnnmap_parse(ctdb->vnn_map);
951 } else if (strcmp(line, "DBMAP") == 0) {
952 status = dbmap_parse(ctdb->db_map);
953 } else if (strcmp(line, "PUBLICIPS") == 0) {
954 status = public_ips_parse(ctdb,
955 ctdb->node_map->num_nodes);
956 } else if (strcmp(line, "RECLOCK") == 0) {
957 status = reclock_parse(ctdb);
958 } else if (strcmp(line, "CONTROLFAILS") == 0) {
959 status = control_failures_parse(ctdb);
961 fprintf(stderr, "Unknown line %s\n", line);
970 ctdb->start_time = tevent_timeval_current();
971 ctdb->recovery_start_time = tevent_timeval_current();
972 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
973 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
974 ctdb->vnn_map->generation =
975 new_generation(ctdb->vnn_map->generation);
977 ctdb->recovery_end_time = tevent_timeval_current();
979 ctdb->log_level = DEBUG_ERR;
980 ctdb->runstate = CTDB_RUNSTATE_RUNNING;
982 ctdb_tunable_set_defaults(&ctdb->tun_list);
991 static bool ctdbd_verify(struct ctdbd_context *ctdb)
996 if (ctdb->node_map->num_nodes == 0) {
1000 /* Make sure all the nodes are in order */
1001 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1002 node = &ctdb->node_map->node[i];
1003 if (node->pnn != i) {
1004 fprintf(stderr, "Expected node %u, found %u\n",
1010 node = &ctdb->node_map->node[ctdb->node_map->pnn];
1011 if (node->flags & NODE_FLAGS_DISCONNECTED) {
1012 DEBUG(DEBUG_INFO, ("Node disconnected, exiting\n"));
1023 struct recover_state {
1024 struct tevent_context *ev;
1025 struct ctdbd_context *ctdb;
1028 static int recover_check(struct tevent_req *req);
1029 static void recover_wait_done(struct tevent_req *subreq);
1030 static void recover_done(struct tevent_req *subreq);
1032 static struct tevent_req *recover_send(TALLOC_CTX *mem_ctx,
1033 struct tevent_context *ev,
1034 struct ctdbd_context *ctdb)
1036 struct tevent_req *req;
1037 struct recover_state *state;
1040 req = tevent_req_create(mem_ctx, &state, struct recover_state);
1048 ret = recover_check(req);
1050 tevent_req_error(req, ret);
1051 return tevent_req_post(req, ev);
1057 static int recover_check(struct tevent_req *req)
1059 struct recover_state *state = tevent_req_data(
1060 req, struct recover_state);
1061 struct ctdbd_context *ctdb = state->ctdb;
1062 struct tevent_req *subreq;
1063 bool recovery_disabled;
1066 recovery_disabled = false;
1067 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1068 if (ctdb->node_map->node[i].recovery_disabled) {
1069 recovery_disabled = true;
1074 subreq = tevent_wakeup_send(state, state->ev,
1075 tevent_timeval_current_ofs(1, 0));
1076 if (subreq == NULL) {
1080 if (recovery_disabled) {
1081 tevent_req_set_callback(subreq, recover_wait_done, req);
1083 ctdb->recovery_start_time = tevent_timeval_current();
1084 tevent_req_set_callback(subreq, recover_done, req);
1090 static void recover_wait_done(struct tevent_req *subreq)
1092 struct tevent_req *req = tevent_req_callback_data(
1093 subreq, struct tevent_req);
1097 status = tevent_wakeup_recv(subreq);
1098 TALLOC_FREE(subreq);
1100 tevent_req_error(req, EIO);
1104 ret = recover_check(req);
1106 tevent_req_error(req, ret);
1110 static void recover_done(struct tevent_req *subreq)
1112 struct tevent_req *req = tevent_req_callback_data(
1113 subreq, struct tevent_req);
1114 struct recover_state *state = tevent_req_data(
1115 req, struct recover_state);
1116 struct ctdbd_context *ctdb = state->ctdb;
1119 status = tevent_wakeup_recv(subreq);
1120 TALLOC_FREE(subreq);
1122 tevent_req_error(req, EIO);
1126 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1127 ctdb->recovery_end_time = tevent_timeval_current();
1128 ctdb->vnn_map->generation = new_generation(ctdb->vnn_map->generation);
1130 tevent_req_done(req);
1133 static bool recover_recv(struct tevent_req *req, int *perr)
1137 if (tevent_req_is_unix_error(req, &err)) {
1148 * Routines for ctdb_req_header
1151 static void header_fix_pnn(struct ctdb_req_header *header,
1152 struct ctdbd_context *ctdb)
1154 if (header->srcnode == CTDB_CURRENT_NODE) {
1155 header->srcnode = ctdb->node_map->pnn;
1158 if (header->destnode == CTDB_CURRENT_NODE) {
1159 header->destnode = ctdb->node_map->pnn;
1163 static struct ctdb_req_header header_reply_control(
1164 struct ctdb_req_header *header,
1165 struct ctdbd_context *ctdb)
1167 struct ctdb_req_header reply_header;
1169 reply_header = (struct ctdb_req_header) {
1170 .ctdb_magic = CTDB_MAGIC,
1171 .ctdb_version = CTDB_PROTOCOL,
1172 .generation = ctdb->vnn_map->generation,
1173 .operation = CTDB_REPLY_CONTROL,
1174 .destnode = header->srcnode,
1175 .srcnode = header->destnode,
1176 .reqid = header->reqid,
1179 return reply_header;
1182 static struct ctdb_req_header header_reply_message(
1183 struct ctdb_req_header *header,
1184 struct ctdbd_context *ctdb)
1186 struct ctdb_req_header reply_header;
1188 reply_header = (struct ctdb_req_header) {
1189 .ctdb_magic = CTDB_MAGIC,
1190 .ctdb_version = CTDB_PROTOCOL,
1191 .generation = ctdb->vnn_map->generation,
1192 .operation = CTDB_REQ_MESSAGE,
1193 .destnode = header->srcnode,
1194 .srcnode = header->destnode,
1198 return reply_header;
1205 struct client_state {
1206 struct tevent_context *ev;
1208 struct ctdbd_context *ctdb;
1211 struct comm_context *comm;
1212 struct srvid_register_state *rstate;
1217 * Send replies to controls and messages
1220 static void client_reply_done(struct tevent_req *subreq);
1222 static void client_send_message(struct tevent_req *req,
1223 struct ctdb_req_header *header,
1224 struct ctdb_req_message_data *message)
1226 struct client_state *state = tevent_req_data(
1227 req, struct client_state);
1228 struct ctdbd_context *ctdb = state->ctdb;
1229 struct tevent_req *subreq;
1230 struct ctdb_req_header reply_header;
1232 size_t datalen, buflen;
1235 reply_header = header_reply_message(header, ctdb);
1237 datalen = ctdb_req_message_data_len(&reply_header, message);
1238 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1240 tevent_req_error(req, ret);
1244 ret = ctdb_req_message_data_push(&reply_header, message,
1247 tevent_req_error(req, ret);
1251 DEBUG(DEBUG_INFO, ("message srvid = 0x%"PRIx64"\n", message->srvid));
1253 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1254 if (tevent_req_nomem(subreq, req)) {
1257 tevent_req_set_callback(subreq, client_reply_done, req);
1259 talloc_steal(subreq, buf);
1262 static void client_send_control(struct tevent_req *req,
1263 struct ctdb_req_header *header,
1264 struct ctdb_reply_control *reply)
1266 struct client_state *state = tevent_req_data(
1267 req, struct client_state);
1268 struct ctdbd_context *ctdb = state->ctdb;
1269 struct tevent_req *subreq;
1270 struct ctdb_req_header reply_header;
1272 size_t datalen, buflen;
1275 reply_header = header_reply_control(header, ctdb);
1277 datalen = ctdb_reply_control_len(&reply_header, reply);
1278 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1280 tevent_req_error(req, ret);
1284 ret = ctdb_reply_control_push(&reply_header, reply, buf, &buflen);
1286 tevent_req_error(req, ret);
1290 DEBUG(DEBUG_INFO, ("reply opcode = %u\n", reply->rdata.opcode));
1292 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1293 if (tevent_req_nomem(subreq, req)) {
1296 tevent_req_set_callback(subreq, client_reply_done, req);
1298 talloc_steal(subreq, buf);
1301 static void client_reply_done(struct tevent_req *subreq)
1303 struct tevent_req *req = tevent_req_callback_data(
1304 subreq, struct tevent_req);
1308 status = comm_write_recv(subreq, &ret);
1309 TALLOC_FREE(subreq);
1311 tevent_req_error(req, ret);
1316 * Handling protocol - controls
1319 static void control_process_exists(TALLOC_CTX *mem_ctx,
1320 struct tevent_req *req,
1321 struct ctdb_req_header *header,
1322 struct ctdb_req_control *request)
1324 struct client_state *state = tevent_req_data(
1325 req, struct client_state);
1326 struct ctdbd_context *ctdb = state->ctdb;
1327 struct client_state *cstate;
1328 struct ctdb_reply_control reply;
1330 reply.rdata.opcode = request->opcode;
1332 cstate = client_find(ctdb, request->rdata.data.pid);
1333 if (cstate == NULL) {
1335 reply.errmsg = "No client for PID";
1337 reply.status = kill(request->rdata.data.pid, 0);
1338 reply.errmsg = NULL;
1341 client_send_control(req, header, &reply);
1344 static void control_ping(TALLOC_CTX *mem_ctx,
1345 struct tevent_req *req,
1346 struct ctdb_req_header *header,
1347 struct ctdb_req_control *request)
1349 struct client_state *state = tevent_req_data(
1350 req, struct client_state);
1351 struct ctdbd_context *ctdb = state->ctdb;
1352 struct ctdb_reply_control reply;
1354 reply.rdata.opcode = request->opcode;
1355 reply.status = ctdb->num_clients;
1356 reply.errmsg = NULL;
1358 client_send_control(req, header, &reply);
1361 static void control_getdbpath(TALLOC_CTX *mem_ctx,
1362 struct tevent_req *req,
1363 struct ctdb_req_header *header,
1364 struct ctdb_req_control *request)
1366 struct client_state *state = tevent_req_data(
1367 req, struct client_state);
1368 struct ctdbd_context *ctdb = state->ctdb;
1369 struct ctdb_reply_control reply;
1370 struct database *db;
1372 reply.rdata.opcode = request->opcode;
1374 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1376 reply.status = ENOENT;
1377 reply.errmsg = "Database not found";
1380 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
1381 base = "/var/lib/ctdb/persistent";
1383 base = "/var/run/ctdb/DB_DIR";
1385 reply.rdata.data.db_path =
1386 talloc_asprintf(mem_ctx, "%s/%s.%u",
1387 base, db->name, header->destnode);
1388 if (reply.rdata.data.db_path == NULL) {
1389 reply.status = ENOMEM;
1390 reply.errmsg = "Memory error";
1393 reply.errmsg = NULL;
1397 client_send_control(req, header, &reply);
1400 static void control_getvnnmap(TALLOC_CTX *mem_ctx,
1401 struct tevent_req *req,
1402 struct ctdb_req_header *header,
1403 struct ctdb_req_control *request)
1405 struct client_state *state = tevent_req_data(
1406 req, struct client_state);
1407 struct ctdbd_context *ctdb = state->ctdb;
1408 struct ctdb_reply_control reply;
1409 struct ctdb_vnn_map *vnnmap;
1411 reply.rdata.opcode = request->opcode;
1413 vnnmap = talloc_zero(mem_ctx, struct ctdb_vnn_map);
1414 if (vnnmap == NULL) {
1415 reply.status = ENOMEM;
1416 reply.errmsg = "Memory error";
1418 vnnmap->generation = ctdb->vnn_map->generation;
1419 vnnmap->size = ctdb->vnn_map->size;
1420 vnnmap->map = ctdb->vnn_map->map;
1422 reply.rdata.data.vnnmap = vnnmap;
1424 reply.errmsg = NULL;
1427 client_send_control(req, header, &reply);
1430 static void control_get_debug(TALLOC_CTX *mem_ctx,
1431 struct tevent_req *req,
1432 struct ctdb_req_header *header,
1433 struct ctdb_req_control *request)
1435 struct client_state *state = tevent_req_data(
1436 req, struct client_state);
1437 struct ctdbd_context *ctdb = state->ctdb;
1438 struct ctdb_reply_control reply;
1440 reply.rdata.opcode = request->opcode;
1441 reply.rdata.data.loglevel = (uint32_t)ctdb->log_level;
1443 reply.errmsg = NULL;
1445 client_send_control(req, header, &reply);
1448 static void control_set_debug(TALLOC_CTX *mem_ctx,
1449 struct tevent_req *req,
1450 struct ctdb_req_header *header,
1451 struct ctdb_req_control *request)
1453 struct client_state *state = tevent_req_data(
1454 req, struct client_state);
1455 struct ctdbd_context *ctdb = state->ctdb;
1456 struct ctdb_reply_control reply;
1458 ctdb->log_level = (int)request->rdata.data.loglevel;
1460 reply.rdata.opcode = request->opcode;
1462 reply.errmsg = NULL;
1464 client_send_control(req, header, &reply);
1467 static void control_get_dbmap(TALLOC_CTX *mem_ctx,
1468 struct tevent_req *req,
1469 struct ctdb_req_header *header,
1470 struct ctdb_req_control *request)
1472 struct client_state *state = tevent_req_data(
1473 req, struct client_state);
1474 struct ctdbd_context *ctdb = state->ctdb;
1475 struct ctdb_reply_control reply;
1476 struct ctdb_dbid_map *dbmap;
1479 reply.rdata.opcode = request->opcode;
1481 dbmap = talloc_zero(mem_ctx, struct ctdb_dbid_map);
1482 if (dbmap == NULL) {
1486 dbmap->num = ctdb->db_map->num_dbs;
1487 dbmap->dbs = talloc_zero_array(dbmap, struct ctdb_dbid, dbmap->num);
1488 if (dbmap->dbs == NULL) {
1492 for (i = 0; i < dbmap->num; i++) {
1493 struct database *db = &ctdb->db_map->db[i];
1494 dbmap->dbs[i] = (struct ctdb_dbid) {
1500 reply.rdata.data.dbmap = dbmap;
1502 reply.errmsg = NULL;
1503 client_send_control(req, header, &reply);
1508 reply.errmsg = "Memory error";
1509 client_send_control(req, header, &reply);
1512 static void control_get_recmode(TALLOC_CTX *mem_ctx,
1513 struct tevent_req *req,
1514 struct ctdb_req_header *header,
1515 struct ctdb_req_control *request)
1517 struct client_state *state = tevent_req_data(
1518 req, struct client_state);
1519 struct ctdbd_context *ctdb = state->ctdb;
1520 struct ctdb_reply_control reply;
1522 reply.rdata.opcode = request->opcode;
1523 reply.status = ctdb->vnn_map->recmode;
1524 reply.errmsg = NULL;
1526 client_send_control(req, header, &reply);
1529 struct set_recmode_state {
1530 struct tevent_req *req;
1531 struct ctdbd_context *ctdb;
1532 struct ctdb_req_header header;
1533 struct ctdb_reply_control reply;
1536 static void set_recmode_callback(struct tevent_req *subreq)
1538 struct set_recmode_state *substate = tevent_req_callback_data(
1539 subreq, struct set_recmode_state);
1543 status = recover_recv(subreq, &ret);
1544 TALLOC_FREE(subreq);
1546 substate->reply.status = ret;
1547 substate->reply.errmsg = "recovery failed";
1549 substate->reply.status = 0;
1550 substate->reply.errmsg = NULL;
1553 client_send_control(substate->req, &substate->header, &substate->reply);
1554 talloc_free(substate);
1557 static void control_set_recmode(TALLOC_CTX *mem_ctx,
1558 struct tevent_req *req,
1559 struct ctdb_req_header *header,
1560 struct ctdb_req_control *request)
1562 struct client_state *state = tevent_req_data(
1563 req, struct client_state);
1564 struct tevent_req *subreq;
1565 struct ctdbd_context *ctdb = state->ctdb;
1566 struct set_recmode_state *substate;
1567 struct ctdb_reply_control reply;
1569 reply.rdata.opcode = request->opcode;
1571 if (request->rdata.data.recmode == CTDB_RECOVERY_NORMAL) {
1573 reply.errmsg = "Client cannot set recmode to NORMAL";
1577 substate = talloc_zero(ctdb, struct set_recmode_state);
1578 if (substate == NULL) {
1580 reply.errmsg = "Memory error";
1584 substate->req = req;
1585 substate->ctdb = ctdb;
1586 substate->header = *header;
1587 substate->reply.rdata.opcode = request->opcode;
1589 subreq = recover_send(substate, state->ev, state->ctdb);
1590 if (subreq == NULL) {
1591 talloc_free(substate);
1594 tevent_req_set_callback(subreq, set_recmode_callback, substate);
1596 ctdb->vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
1600 client_send_control(req, header, &reply);
1604 static void srvid_handler(uint64_t srvid, TDB_DATA data, void *private_data)
1606 printf("Received a message for SRVID 0x%"PRIx64"\n", srvid);
1609 static void control_register_srvid(TALLOC_CTX *mem_ctx,
1610 struct tevent_req *req,
1611 struct ctdb_req_header *header,
1612 struct ctdb_req_control *request)
1614 struct client_state *state = tevent_req_data(
1615 req, struct client_state);
1616 struct ctdbd_context *ctdb = state->ctdb;
1617 struct ctdb_reply_control reply;
1620 reply.rdata.opcode = request->opcode;
1622 ret = srvid_register(ctdb->srv, state, request->srvid,
1623 srvid_handler, state);
1626 reply.errmsg = "Memory error";
1630 DEBUG(DEBUG_INFO, ("Register srvid 0x%"PRIx64"\n", request->srvid));
1633 reply.errmsg = NULL;
1636 client_send_control(req, header, &reply);
1639 static void control_deregister_srvid(TALLOC_CTX *mem_ctx,
1640 struct tevent_req *req,
1641 struct ctdb_req_header *header,
1642 struct ctdb_req_control *request)
1644 struct client_state *state = tevent_req_data(
1645 req, struct client_state);
1646 struct ctdbd_context *ctdb = state->ctdb;
1647 struct ctdb_reply_control reply;
1650 reply.rdata.opcode = request->opcode;
1652 ret = srvid_deregister(ctdb->srv, request->srvid, state);
1655 reply.errmsg = "srvid not registered";
1659 DEBUG(DEBUG_INFO, ("Deregister srvid 0x%"PRIx64"\n", request->srvid));
1662 reply.errmsg = NULL;
1665 client_send_control(req, header, &reply);
1668 static void control_get_dbname(TALLOC_CTX *mem_ctx,
1669 struct tevent_req *req,
1670 struct ctdb_req_header *header,
1671 struct ctdb_req_control *request)
1673 struct client_state *state = tevent_req_data(
1674 req, struct client_state);
1675 struct ctdbd_context *ctdb = state->ctdb;
1676 struct ctdb_reply_control reply;
1677 struct database *db;
1679 reply.rdata.opcode = request->opcode;
1681 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1683 reply.status = ENOENT;
1684 reply.errmsg = "Database not found";
1686 reply.rdata.data.db_name = talloc_strdup(mem_ctx, db->name);
1687 if (reply.rdata.data.db_name == NULL) {
1688 reply.status = ENOMEM;
1689 reply.errmsg = "Memory error";
1692 reply.errmsg = NULL;
1696 client_send_control(req, header, &reply);
1699 static void control_get_pid(TALLOC_CTX *mem_ctx,
1700 struct tevent_req *req,
1701 struct ctdb_req_header *header,
1702 struct ctdb_req_control *request)
1704 struct ctdb_reply_control reply;
1706 reply.rdata.opcode = request->opcode;
1707 reply.status = getpid();
1708 reply.errmsg = NULL;
1710 client_send_control(req, header, &reply);
1713 static void control_get_recmaster(TALLOC_CTX *mem_ctx,
1714 struct tevent_req *req,
1715 struct ctdb_req_header *header,
1716 struct ctdb_req_control *request)
1718 struct client_state *state = tevent_req_data(
1719 req, struct client_state);
1720 struct ctdbd_context *ctdb = state->ctdb;
1721 struct ctdb_reply_control reply;
1723 reply.rdata.opcode = request->opcode;
1724 reply.status = ctdb->node_map->recmaster;
1725 reply.errmsg = NULL;
1727 client_send_control(req, header, &reply);
1730 static void control_get_pnn(TALLOC_CTX *mem_ctx,
1731 struct tevent_req *req,
1732 struct ctdb_req_header *header,
1733 struct ctdb_req_control *request)
1735 struct ctdb_reply_control reply;
1737 reply.rdata.opcode = request->opcode;
1738 reply.status = header->destnode;
1739 reply.errmsg = NULL;
1741 client_send_control(req, header, &reply);
1744 static void control_shutdown(TALLOC_CTX *mem_ctx,
1745 struct tevent_req *req,
1746 struct ctdb_req_header *hdr,
1747 struct ctdb_req_control *request)
1749 struct client_state *state = tevent_req_data(
1750 req, struct client_state);
1755 static void control_set_tunable(TALLOC_CTX *mem_ctx,
1756 struct tevent_req *req,
1757 struct ctdb_req_header *header,
1758 struct ctdb_req_control *request)
1760 struct client_state *state = tevent_req_data(
1761 req, struct client_state);
1762 struct ctdbd_context *ctdb = state->ctdb;
1763 struct ctdb_reply_control reply;
1766 reply.rdata.opcode = request->opcode;
1767 reply.errmsg = NULL;
1769 ret = ctdb_tunable_set_value(&ctdb->tun_list,
1770 request->rdata.data.tunable->name,
1771 request->rdata.data.tunable->value,
1775 } else if (obsolete) {
1781 client_send_control(req, header, &reply);
1784 static void control_get_tunable(TALLOC_CTX *mem_ctx,
1785 struct tevent_req *req,
1786 struct ctdb_req_header *header,
1787 struct ctdb_req_control *request)
1789 struct client_state *state = tevent_req_data(
1790 req, struct client_state);
1791 struct ctdbd_context *ctdb = state->ctdb;
1792 struct ctdb_reply_control reply;
1796 reply.rdata.opcode = request->opcode;
1797 reply.errmsg = NULL;
1799 ret = ctdb_tunable_get_value(&ctdb->tun_list,
1800 request->rdata.data.tun_var, &value);
1804 reply.rdata.data.tun_value = value;
1808 client_send_control(req, header, &reply);
1811 static void control_list_tunables(TALLOC_CTX *mem_ctx,
1812 struct tevent_req *req,
1813 struct ctdb_req_header *header,
1814 struct ctdb_req_control *request)
1816 struct ctdb_reply_control reply;
1817 struct ctdb_var_list *var_list;
1819 reply.rdata.opcode = request->opcode;
1820 reply.errmsg = NULL;
1822 var_list = ctdb_tunable_names(mem_ctx);
1823 if (var_list == NULL) {
1826 reply.rdata.data.tun_var_list = var_list;
1830 client_send_control(req, header, &reply);
1833 static void control_modify_flags(TALLOC_CTX *mem_ctx,
1834 struct tevent_req *req,
1835 struct ctdb_req_header *header,
1836 struct ctdb_req_control *request)
1838 struct client_state *state = tevent_req_data(
1839 req, struct client_state);
1840 struct ctdbd_context *ctdb = state->ctdb;
1841 struct ctdb_node_flag_change *change = request->rdata.data.flag_change;
1842 struct ctdb_reply_control reply;
1845 reply.rdata.opcode = request->opcode;
1847 if ((change->old_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) ||
1848 (change->new_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
1850 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
1851 reply.status = EINVAL;
1852 reply.errmsg = "Failed to MODIFY_FLAGS";
1853 client_send_control(req, header, &reply);
1857 /* There's all sorts of broadcast weirdness here. Only change
1858 * the specified node, not the destination node of the
1860 node = &ctdb->node_map->node[change->pnn];
1863 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0 &&
1864 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
1865 DEBUG(DEBUG_INFO,("Disabling node %d\n", header->destnode));
1866 node->flags |= NODE_FLAGS_PERMANENTLY_DISABLED;
1871 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0 &&
1872 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0) {
1873 DEBUG(DEBUG_INFO,("Enabling node %d\n", header->destnode));
1874 node->flags &= ~NODE_FLAGS_PERMANENTLY_DISABLED;
1878 DEBUG(DEBUG_INFO, ("Flags unchanged for node %d\n", header->destnode));
1882 reply.errmsg = NULL;
1883 client_send_control(req, header, &reply);
1886 static void control_get_all_tunables(TALLOC_CTX *mem_ctx,
1887 struct tevent_req *req,
1888 struct ctdb_req_header *header,
1889 struct ctdb_req_control *request)
1891 struct client_state *state = tevent_req_data(
1892 req, struct client_state);
1893 struct ctdbd_context *ctdb = state->ctdb;
1894 struct ctdb_reply_control reply;
1896 reply.rdata.opcode = request->opcode;
1897 reply.rdata.data.tun_list = &ctdb->tun_list;
1899 reply.errmsg = NULL;
1901 client_send_control(req, header, &reply);
1904 static void control_uptime(TALLOC_CTX *mem_ctx,
1905 struct tevent_req *req,
1906 struct ctdb_req_header *header,
1907 struct ctdb_req_control *request)
1909 struct client_state *state = tevent_req_data(
1910 req, struct client_state);
1911 struct ctdbd_context *ctdb = state->ctdb;
1912 struct ctdb_reply_control reply;
1913 struct ctdb_uptime *uptime;;
1915 reply.rdata.opcode = request->opcode;
1917 uptime = talloc_zero(mem_ctx, struct ctdb_uptime);
1918 if (uptime == NULL) {
1922 uptime->current_time = tevent_timeval_current();
1923 uptime->ctdbd_start_time = ctdb->start_time;
1924 uptime->last_recovery_started = ctdb->recovery_start_time;
1925 uptime->last_recovery_finished = ctdb->recovery_end_time;
1927 reply.rdata.data.uptime = uptime;
1929 reply.errmsg = NULL;
1930 client_send_control(req, header, &reply);
1935 reply.errmsg = "Memory error";
1936 client_send_control(req, header, &reply);
1939 static void control_reload_nodes_file(TALLOC_CTX *mem_ctx,
1940 struct tevent_req *req,
1941 struct ctdb_req_header *header,
1942 struct ctdb_req_control *request)
1944 struct client_state *state = tevent_req_data(
1945 req, struct client_state);
1946 struct ctdbd_context *ctdb = state->ctdb;
1947 struct ctdb_reply_control reply;
1948 struct ctdb_node_map *nodemap;
1949 struct node_map *node_map = ctdb->node_map;
1952 reply.rdata.opcode = request->opcode;
1954 nodemap = read_nodes_file(mem_ctx, header->destnode);
1955 if (nodemap == NULL) {
1959 for (i=0; i<nodemap->num; i++) {
1962 if (i < node_map->num_nodes &&
1963 ctdb_sock_addr_same(&nodemap->node[i].addr,
1964 &node_map->node[i].addr)) {
1968 if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
1971 node = &node_map->node[i];
1973 node->flags |= NODE_FLAGS_DELETED;
1974 ret = ctdb_sock_addr_from_string("0.0.0.0", &node->addr,
1977 /* Can't happen, but Coverity... */
1984 if (i < node_map->num_nodes &&
1985 node_map->node[i].flags & NODE_FLAGS_DELETED) {
1986 node = &node_map->node[i];
1988 node->flags &= ~NODE_FLAGS_DELETED;
1989 node->addr = nodemap->node[i].addr;
1994 node_map->node = talloc_realloc(node_map, node_map->node,
1996 node_map->num_nodes+1);
1997 if (node_map->node == NULL) {
2000 node = &node_map->node[node_map->num_nodes];
2002 node->addr = nodemap->node[i].addr;
2003 node->pnn = nodemap->node[i].pnn;
2005 node->capabilities = CTDB_CAP_DEFAULT;
2006 node->recovery_disabled = false;
2007 node->recovery_substate = NULL;
2009 node_map->num_nodes += 1;
2012 talloc_free(nodemap);
2015 reply.errmsg = NULL;
2016 client_send_control(req, header, &reply);
2021 reply.errmsg = "Memory error";
2022 client_send_control(req, header, &reply);
2025 static void control_get_capabilities(TALLOC_CTX *mem_ctx,
2026 struct tevent_req *req,
2027 struct ctdb_req_header *header,
2028 struct ctdb_req_control *request)
2030 struct client_state *state = tevent_req_data(
2031 req, struct client_state);
2032 struct ctdbd_context *ctdb = state->ctdb;
2033 struct ctdb_reply_control reply;
2037 reply.rdata.opcode = request->opcode;
2039 node = &ctdb->node_map->node[header->destnode];
2040 caps = node->capabilities;
2042 if (node->flags & NODE_FLAGS_FAKE_TIMEOUT) {
2043 /* Don't send reply */
2047 reply.rdata.data.caps = caps;
2049 reply.errmsg = NULL;
2051 client_send_control(req, header, &reply);
2054 static void control_release_ip(TALLOC_CTX *mem_ctx,
2055 struct tevent_req *req,
2056 struct ctdb_req_header *header,
2057 struct ctdb_req_control *request)
2059 struct client_state *state = tevent_req_data(
2060 req, struct client_state);
2061 struct ctdbd_context *ctdb = state->ctdb;
2062 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2063 struct ctdb_reply_control reply;
2064 struct ctdb_public_ip_list *ips = NULL;
2065 struct ctdb_public_ip *t = NULL;
2068 reply.rdata.opcode = request->opcode;
2070 if (ctdb->known_ips == NULL) {
2071 D_INFO("RELEASE_IP %s - not a public IP\n",
2072 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2076 ips = &ctdb->known_ips[header->destnode];
2079 for (i = 0; i < ips->num; i++) {
2080 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2086 D_INFO("RELEASE_IP %s - not a public IP\n",
2087 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2091 if (t->pnn != header->destnode) {
2092 if (header->destnode == ip->pnn) {
2093 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2094 ctdb_sock_addr_to_string(mem_ctx,
2098 reply.errmsg = "RELEASE_IP to TAKE_IP node";
2099 client_send_control(req, header, &reply);
2103 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2104 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2108 D_NOTICE("RELEASE_IP %s - to node %d\n",
2109 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2116 reply.errmsg = NULL;
2117 client_send_control(req, header, &reply);
2120 static void control_takeover_ip(TALLOC_CTX *mem_ctx,
2121 struct tevent_req *req,
2122 struct ctdb_req_header *header,
2123 struct ctdb_req_control *request)
2125 struct client_state *state = tevent_req_data(
2126 req, struct client_state);
2127 struct ctdbd_context *ctdb = state->ctdb;
2128 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2129 struct ctdb_reply_control reply;
2130 struct ctdb_public_ip_list *ips = NULL;
2131 struct ctdb_public_ip *t = NULL;
2134 reply.rdata.opcode = request->opcode;
2136 if (ctdb->known_ips == NULL) {
2137 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2138 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2142 ips = &ctdb->known_ips[header->destnode];
2145 for (i = 0; i < ips->num; i++) {
2146 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2152 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2153 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2157 if (t->pnn == header->destnode) {
2158 D_INFO("TAKEOVER_IP %s - redundant\n",
2159 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2161 D_NOTICE("TAKEOVER_IP %s\n",
2162 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2168 reply.errmsg = NULL;
2169 client_send_control(req, header, &reply);
2172 static void control_get_public_ips(TALLOC_CTX *mem_ctx,
2173 struct tevent_req *req,
2174 struct ctdb_req_header *header,
2175 struct ctdb_req_control *request)
2177 struct client_state *state = tevent_req_data(
2178 req, struct client_state);
2179 struct ctdbd_context *ctdb = state->ctdb;
2180 struct ctdb_reply_control reply;
2181 struct ctdb_public_ip_list *ips = NULL;
2183 reply.rdata.opcode = request->opcode;
2185 if (ctdb->known_ips == NULL) {
2186 /* No IPs defined so create a dummy empty struct and ship it */
2187 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2189 reply.status = ENOMEM;
2190 reply.errmsg = "Memory error";
2196 ips = &ctdb->known_ips[header->destnode];
2198 if (request->flags & CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE) {
2199 /* If runstate is not RUNNING or a node is then return
2200 * no available IPs. Don't worry about interface
2201 * states here - we're not faking down to that level.
2203 if (ctdb->runstate != CTDB_RUNSTATE_RUNNING) {
2204 /* No available IPs: return dummy empty struct */
2205 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2207 reply.status = ENOMEM;
2208 reply.errmsg = "Memory error";
2215 reply.rdata.data.pubip_list = ips;
2217 reply.errmsg = NULL;
2220 client_send_control(req, header, &reply);
2223 static void control_get_nodemap(TALLOC_CTX *mem_ctx,
2224 struct tevent_req *req,
2225 struct ctdb_req_header *header,
2226 struct ctdb_req_control *request)
2228 struct client_state *state = tevent_req_data(
2229 req, struct client_state);
2230 struct ctdbd_context *ctdb = state->ctdb;
2231 struct ctdb_reply_control reply;
2232 struct ctdb_node_map *nodemap;
2236 reply.rdata.opcode = request->opcode;
2238 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
2239 if (nodemap == NULL) {
2243 nodemap->num = ctdb->node_map->num_nodes;
2244 nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2246 if (nodemap->node == NULL) {
2250 for (i=0; i<nodemap->num; i++) {
2251 node = &ctdb->node_map->node[i];
2252 nodemap->node[i] = (struct ctdb_node_and_flags) {
2254 .flags = node->flags,
2259 reply.rdata.data.nodemap = nodemap;
2261 reply.errmsg = NULL;
2262 client_send_control(req, header, &reply);
2267 reply.errmsg = "Memory error";
2268 client_send_control(req, header, &reply);
2271 static void control_get_reclock_file(TALLOC_CTX *mem_ctx,
2272 struct tevent_req *req,
2273 struct ctdb_req_header *header,
2274 struct ctdb_req_control *request)
2276 struct client_state *state = tevent_req_data(
2277 req, struct client_state);
2278 struct ctdbd_context *ctdb = state->ctdb;
2279 struct ctdb_reply_control reply;
2281 reply.rdata.opcode = request->opcode;
2283 if (ctdb->reclock != NULL) {
2284 reply.rdata.data.reclock_file =
2285 talloc_strdup(mem_ctx, ctdb->reclock);
2286 if (reply.rdata.data.reclock_file == NULL) {
2287 reply.status = ENOMEM;
2288 reply.errmsg = "Memory error";
2292 reply.rdata.data.reclock_file = NULL;
2296 reply.errmsg = NULL;
2299 client_send_control(req, header, &reply);
2302 static void control_stop_node(TALLOC_CTX *mem_ctx,
2303 struct tevent_req *req,
2304 struct ctdb_req_header *header,
2305 struct ctdb_req_control *request)
2307 struct client_state *state = tevent_req_data(
2308 req, struct client_state);
2309 struct ctdbd_context *ctdb = state->ctdb;
2310 struct ctdb_reply_control reply;
2312 reply.rdata.opcode = request->opcode;
2314 DEBUG(DEBUG_INFO, ("Stopping node\n"));
2315 ctdb->node_map->node[header->destnode].flags |= NODE_FLAGS_STOPPED;
2318 reply.errmsg = NULL;
2320 client_send_control(req, header, &reply);
2324 static void control_continue_node(TALLOC_CTX *mem_ctx,
2325 struct tevent_req *req,
2326 struct ctdb_req_header *header,
2327 struct ctdb_req_control *request)
2329 struct client_state *state = tevent_req_data(
2330 req, struct client_state);
2331 struct ctdbd_context *ctdb = state->ctdb;
2332 struct ctdb_reply_control reply;
2334 reply.rdata.opcode = request->opcode;
2336 DEBUG(DEBUG_INFO, ("Continue node\n"));
2337 ctdb->node_map->node[header->destnode].flags &= ~NODE_FLAGS_STOPPED;
2340 reply.errmsg = NULL;
2342 client_send_control(req, header, &reply);
2346 static void set_ban_state_callback(struct tevent_req *subreq)
2348 struct node *node = tevent_req_callback_data(
2349 subreq, struct node);
2352 status = tevent_wakeup_recv(subreq);
2353 TALLOC_FREE(subreq);
2355 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2358 node->flags &= ~NODE_FLAGS_BANNED;
2361 static void control_set_ban_state(TALLOC_CTX *mem_ctx,
2362 struct tevent_req *req,
2363 struct ctdb_req_header *header,
2364 struct ctdb_req_control *request)
2366 struct client_state *state = tevent_req_data(
2367 req, struct client_state);
2368 struct tevent_req *subreq;
2369 struct ctdbd_context *ctdb = state->ctdb;
2370 struct ctdb_ban_state *ban = request->rdata.data.ban_state;
2371 struct ctdb_reply_control reply;
2374 reply.rdata.opcode = request->opcode;
2376 if (ban->pnn != header->destnode) {
2378 ("SET_BAN_STATE control for PNN %d rejected\n",
2380 reply.status = EINVAL;
2384 node = &ctdb->node_map->node[header->destnode];
2386 if (ban->time == 0) {
2387 DEBUG(DEBUG_INFO,("Unbanning this node\n"));
2388 node->flags &= ~NODE_FLAGS_BANNED;
2392 subreq = tevent_wakeup_send(ctdb->node_map, state->ev,
2393 tevent_timeval_current_ofs(
2395 if (subreq == NULL) {
2396 reply.status = ENOMEM;
2399 tevent_req_set_callback(subreq, set_ban_state_callback, node);
2401 DEBUG(DEBUG_INFO, ("Banning this node for %d seconds\n", ban->time));
2402 node->flags |= NODE_FLAGS_BANNED;
2403 ctdb->vnn_map->generation = INVALID_GENERATION;
2407 reply.errmsg = NULL;
2409 client_send_control(req, header, &reply);
2413 reply.errmsg = "Failed to ban node";
2416 static void control_get_db_seqnum(TALLOC_CTX *mem_ctx,
2417 struct tevent_req *req,
2418 struct ctdb_req_header *header,
2419 struct ctdb_req_control *request)
2421 struct client_state *state = tevent_req_data(
2422 req, struct client_state);
2423 struct ctdbd_context *ctdb = state->ctdb;
2424 struct ctdb_reply_control reply;
2425 struct database *db;
2427 reply.rdata.opcode = request->opcode;
2429 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2431 reply.status = ENOENT;
2432 reply.errmsg = "Database not found";
2434 reply.rdata.data.seqnum = db->seq_num;
2436 reply.errmsg = NULL;
2439 client_send_control(req, header, &reply);
2442 static void control_db_get_health(TALLOC_CTX *mem_ctx,
2443 struct tevent_req *req,
2444 struct ctdb_req_header *header,
2445 struct ctdb_req_control *request)
2447 struct client_state *state = tevent_req_data(
2448 req, struct client_state);
2449 struct ctdbd_context *ctdb = state->ctdb;
2450 struct ctdb_reply_control reply;
2451 struct database *db;
2453 reply.rdata.opcode = request->opcode;
2455 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2457 reply.status = ENOENT;
2458 reply.errmsg = "Database not found";
2460 reply.rdata.data.reason = NULL;
2462 reply.errmsg = NULL;
2465 client_send_control(req, header, &reply);
2468 static struct ctdb_iface_list *get_ctdb_iface_list(TALLOC_CTX *mem_ctx,
2469 struct ctdbd_context *ctdb)
2471 struct ctdb_iface_list *iface_list;
2472 struct interface *iface;
2475 iface_list = talloc_zero(mem_ctx, struct ctdb_iface_list);
2476 if (iface_list == NULL) {
2480 iface_list->num = ctdb->iface_map->num;
2481 iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2483 if (iface_list->iface == NULL) {
2484 TALLOC_FREE(iface_list);
2488 for (i=0; i<iface_list->num; i++) {
2489 iface = &ctdb->iface_map->iface[i];
2490 iface_list->iface[i] = (struct ctdb_iface) {
2491 .link_state = iface->link_up,
2492 .references = iface->references,
2494 strlcpy(iface_list->iface[i].name, iface->name,
2495 sizeof(iface_list->iface[i].name));
2502 static void control_get_public_ip_info(TALLOC_CTX *mem_ctx,
2503 struct tevent_req *req,
2504 struct ctdb_req_header *header,
2505 struct ctdb_req_control *request)
2507 struct client_state *state = tevent_req_data(
2508 req, struct client_state);
2509 struct ctdbd_context *ctdb = state->ctdb;
2510 struct ctdb_reply_control reply;
2511 ctdb_sock_addr *addr = request->rdata.data.addr;
2512 struct ctdb_public_ip_list *known = NULL;
2513 struct ctdb_public_ip_info *info = NULL;
2516 reply.rdata.opcode = request->opcode;
2518 info = talloc_zero(mem_ctx, struct ctdb_public_ip_info);
2520 reply.status = ENOMEM;
2521 reply.errmsg = "Memory error";
2525 reply.rdata.data.ipinfo = info;
2527 if (ctdb->known_ips != NULL) {
2528 known = &ctdb->known_ips[header->destnode];
2530 /* No IPs defined so create a dummy empty struct and
2531 * fall through. The given IP won't be matched
2534 known = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2535 if (known == NULL) {
2536 reply.status = ENOMEM;
2537 reply.errmsg = "Memory error";
2542 for (i = 0; i < known->num; i++) {
2543 if (ctdb_sock_addr_same_ip(&known->ip[i].addr,
2549 if (i == known->num) {
2550 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
2551 ctdb_sock_addr_to_string(mem_ctx, addr, false));
2553 reply.errmsg = "Unknown address";
2557 info->ip = known->ip[i];
2559 /* The fake PUBLICIPS stanza and resulting known_ips data
2560 * don't know anything about interfaces, so completely fake
2563 info->active_idx = 0;
2565 info->ifaces = get_ctdb_iface_list(mem_ctx, ctdb);
2566 if (info->ifaces == NULL) {
2567 reply.status = ENOMEM;
2568 reply.errmsg = "Memory error";
2573 reply.errmsg = NULL;
2576 client_send_control(req, header, &reply);
2579 static void control_get_ifaces(TALLOC_CTX *mem_ctx,
2580 struct tevent_req *req,
2581 struct ctdb_req_header *header,
2582 struct ctdb_req_control *request)
2584 struct client_state *state = tevent_req_data(
2585 req, struct client_state);
2586 struct ctdbd_context *ctdb = state->ctdb;
2587 struct ctdb_reply_control reply;
2588 struct ctdb_iface_list *iface_list;
2590 reply.rdata.opcode = request->opcode;
2592 iface_list = get_ctdb_iface_list(mem_ctx, ctdb);
2593 if (iface_list == NULL) {
2597 reply.rdata.data.iface_list = iface_list;
2599 reply.errmsg = NULL;
2600 client_send_control(req, header, &reply);
2605 reply.errmsg = "Memory error";
2606 client_send_control(req, header, &reply);
2609 static void control_set_iface_link_state(TALLOC_CTX *mem_ctx,
2610 struct tevent_req *req,
2611 struct ctdb_req_header *header,
2612 struct ctdb_req_control *request)
2614 struct client_state *state = tevent_req_data(
2615 req, struct client_state);
2616 struct ctdbd_context *ctdb = state->ctdb;
2617 struct ctdb_reply_control reply;
2618 struct ctdb_iface *in_iface;
2619 struct interface *iface = NULL;
2620 bool link_up = false;
2623 reply.rdata.opcode = request->opcode;
2625 in_iface = request->rdata.data.iface;
2627 if (in_iface->name[CTDB_IFACE_SIZE] != '\0') {
2628 reply.errmsg = "interface name not terminated";
2632 switch (in_iface->link_state) {
2642 reply.errmsg = "invalid link state";
2646 if (in_iface->references != 0) {
2647 reply.errmsg = "references should be 0";
2651 for (i=0; i<ctdb->iface_map->num; i++) {
2652 if (strcmp(ctdb->iface_map->iface[i].name,
2653 in_iface->name) == 0) {
2654 iface = &ctdb->iface_map->iface[i];
2659 if (iface == NULL) {
2660 reply.errmsg = "interface not found";
2664 iface->link_up = link_up;
2667 reply.errmsg = NULL;
2668 client_send_control(req, header, &reply);
2673 client_send_control(req, header, &reply);
2676 static void control_set_db_readonly(TALLOC_CTX *mem_ctx,
2677 struct tevent_req *req,
2678 struct ctdb_req_header *header,
2679 struct ctdb_req_control *request)
2681 struct client_state *state = tevent_req_data(
2682 req, struct client_state);
2683 struct ctdbd_context *ctdb = state->ctdb;
2684 struct ctdb_reply_control reply;
2685 struct database *db;
2687 reply.rdata.opcode = request->opcode;
2689 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2691 reply.status = ENOENT;
2692 reply.errmsg = "Database not found";
2696 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
2697 reply.status = EINVAL;
2698 reply.errmsg = "Can not set READONLY on persistent db";
2702 db->flags |= CTDB_DB_FLAGS_READONLY;
2704 reply.errmsg = NULL;
2707 client_send_control(req, header, &reply);
2710 static void control_set_db_sticky(TALLOC_CTX *mem_ctx,
2711 struct tevent_req *req,
2712 struct ctdb_req_header *header,
2713 struct ctdb_req_control *request)
2715 struct client_state *state = tevent_req_data(
2716 req, struct client_state);
2717 struct ctdbd_context *ctdb = state->ctdb;
2718 struct ctdb_reply_control reply;
2719 struct database *db;
2721 reply.rdata.opcode = request->opcode;
2723 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2725 reply.status = ENOENT;
2726 reply.errmsg = "Database not found";
2730 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
2731 reply.status = EINVAL;
2732 reply.errmsg = "Can not set STICKY on persistent db";
2736 db->flags |= CTDB_DB_FLAGS_STICKY;
2738 reply.errmsg = NULL;
2741 client_send_control(req, header, &reply);
2744 static void control_ipreallocated(TALLOC_CTX *mem_ctx,
2745 struct tevent_req *req,
2746 struct ctdb_req_header *header,
2747 struct ctdb_req_control *request)
2749 struct ctdb_reply_control reply;
2751 /* Always succeed */
2752 reply.rdata.opcode = request->opcode;
2754 reply.errmsg = NULL;
2756 client_send_control(req, header, &reply);
2759 static void control_get_runstate(TALLOC_CTX *mem_ctx,
2760 struct tevent_req *req,
2761 struct ctdb_req_header *header,
2762 struct ctdb_req_control *request)
2764 struct client_state *state = tevent_req_data(
2765 req, struct client_state);
2766 struct ctdbd_context *ctdb = state->ctdb;
2767 struct ctdb_reply_control reply;
2769 reply.rdata.opcode = request->opcode;
2770 reply.rdata.data.runstate = ctdb->runstate;
2772 reply.errmsg = NULL;
2774 client_send_control(req, header, &reply);
2777 static void control_get_nodes_file(TALLOC_CTX *mem_ctx,
2778 struct tevent_req *req,
2779 struct ctdb_req_header *header,
2780 struct ctdb_req_control *request)
2782 struct ctdb_reply_control reply;
2783 struct ctdb_node_map *nodemap;
2785 reply.rdata.opcode = request->opcode;
2787 nodemap = read_nodes_file(mem_ctx, header->destnode);
2788 if (nodemap == NULL) {
2792 reply.rdata.data.nodemap = nodemap;
2794 reply.errmsg = NULL;
2795 client_send_control(req, header, &reply);
2800 reply.errmsg = "Failed to read nodes file";
2801 client_send_control(req, header, &reply);
2804 static void control_check_pid_srvid(TALLOC_CTX *mem_ctx,
2805 struct tevent_req *req,
2806 struct ctdb_req_header *header,
2807 struct ctdb_req_control *request)
2809 struct client_state *state = tevent_req_data(
2810 req, struct client_state);
2811 struct ctdbd_context *ctdb = state->ctdb;
2812 struct ctdb_client *client;
2813 struct client_state *cstate;
2814 struct ctdb_reply_control reply;
2815 bool pid_found, srvid_found;
2818 reply.rdata.opcode = request->opcode;
2821 srvid_found = false;
2823 for (client=ctdb->client_list; client != NULL; client=client->next) {
2824 if (client->pid == request->rdata.data.pid_srvid->pid) {
2826 cstate = (struct client_state *)client->state;
2827 ret = srvid_exists(ctdb->srv,
2828 request->rdata.data.pid_srvid->srvid,
2832 ret = kill(cstate->pid, 0);
2835 reply.errmsg = strerror(errno);
2838 reply.errmsg = NULL;
2846 reply.errmsg = "No client for PID";
2847 } else if (! srvid_found) {
2849 reply.errmsg = "No client for PID and SRVID";
2852 client_send_control(req, header, &reply);
2855 static bool fake_control_failure(TALLOC_CTX *mem_ctx,
2856 struct tevent_req *req,
2857 struct ctdb_req_header *header,
2858 struct ctdb_req_control *request)
2860 struct client_state *state = tevent_req_data(
2861 req, struct client_state);
2862 struct ctdbd_context *ctdb = state->ctdb;
2863 struct ctdb_reply_control reply;
2864 struct fake_control_failure *f = NULL;
2866 D_DEBUG("Checking fake control failure for control %u on node %u\n",
2867 request->opcode, header->destnode);
2868 for (f = ctdb->control_failures; f != NULL; f = f->next) {
2869 if (f->opcode == request->opcode &&
2870 (f->pnn == header->destnode ||
2871 f->pnn == CTDB_UNKNOWN_PNN)) {
2873 reply.rdata.opcode = request->opcode;
2874 if (strcmp(f->error, "TIMEOUT") == 0) {
2875 /* Causes no reply */
2876 D_ERR("Control %u fake timeout on node %u\n",
2877 request->opcode, header->destnode);
2879 } else if (strcmp(f->error, "ERROR") == 0) {
2880 D_ERR("Control %u fake error on node %u\n",
2881 request->opcode, header->destnode);
2883 reply.errmsg = f->comment;
2884 client_send_control(req, header, &reply);
2893 static void control_error(TALLOC_CTX *mem_ctx,
2894 struct tevent_req *req,
2895 struct ctdb_req_header *header,
2896 struct ctdb_req_control *request)
2898 struct ctdb_reply_control reply;
2900 reply.rdata.opcode = request->opcode;
2902 reply.errmsg = "Not implemented";
2904 client_send_control(req, header, &reply);
2908 * Handling protocol - messages
2911 struct disable_recoveries_state {
2915 static void disable_recoveries_callback(struct tevent_req *subreq)
2917 struct disable_recoveries_state *substate = tevent_req_callback_data(
2918 subreq, struct disable_recoveries_state);
2921 status = tevent_wakeup_recv(subreq);
2922 TALLOC_FREE(subreq);
2924 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2927 substate->node->recovery_disabled = false;
2928 TALLOC_FREE(substate->node->recovery_substate);
2931 static void message_disable_recoveries(TALLOC_CTX *mem_ctx,
2932 struct tevent_req *req,
2933 struct ctdb_req_header *header,
2934 struct ctdb_req_message *request)
2936 struct client_state *state = tevent_req_data(
2937 req, struct client_state);
2938 struct tevent_req *subreq;
2939 struct ctdbd_context *ctdb = state->ctdb;
2940 struct disable_recoveries_state *substate;
2941 struct ctdb_disable_message *disable = request->data.disable;
2942 struct ctdb_req_message_data reply;
2947 node = &ctdb->node_map->node[header->destnode];
2949 if (disable->timeout == 0) {
2950 TALLOC_FREE(node->recovery_substate);
2951 node->recovery_disabled = false;
2952 DEBUG(DEBUG_INFO, ("Enabled recoveries on node %u\n",
2957 substate = talloc_zero(ctdb->node_map,
2958 struct disable_recoveries_state);
2959 if (substate == NULL) {
2963 substate->node = node;
2965 subreq = tevent_wakeup_send(substate, state->ev,
2966 tevent_timeval_current_ofs(
2967 disable->timeout, 0));
2968 if (subreq == NULL) {
2969 talloc_free(substate);
2972 tevent_req_set_callback(subreq, disable_recoveries_callback, substate);
2974 DEBUG(DEBUG_INFO, ("Disabled recoveries for %d seconds on node %u\n",
2975 disable->timeout, header->destnode));
2976 node->recovery_substate = substate;
2977 node->recovery_disabled = true;
2980 ret = header->destnode;
2983 reply.srvid = disable->srvid;
2984 data.dptr = (uint8_t *)&ret;
2985 data.dsize = sizeof(int);
2988 client_send_message(req, header, &reply);
2991 static void message_takeover_run(TALLOC_CTX *mem_ctx,
2992 struct tevent_req *req,
2993 struct ctdb_req_header *header,
2994 struct ctdb_req_message *request)
2996 struct client_state *state = tevent_req_data(
2997 req, struct client_state);
2998 struct ctdbd_context *ctdb = state->ctdb;
2999 struct ctdb_srvid_message *srvid = request->data.msg;
3000 struct ctdb_req_message_data reply;
3004 if (header->destnode != ctdb->node_map->recmaster) {
3005 /* No reply! Only recmaster replies... */
3009 DEBUG(DEBUG_INFO, ("IP takover run on node %u\n",
3011 ret = header->destnode;
3013 reply.srvid = srvid->srvid;
3014 data.dptr = (uint8_t *)&ret;
3015 data.dsize = sizeof(int);
3018 client_send_message(req, header, &reply);
3022 * Handle a single client
3025 static void client_read_handler(uint8_t *buf, size_t buflen,
3026 void *private_data);
3027 static void client_dead_handler(void *private_data);
3028 static void client_process_packet(struct tevent_req *req,
3029 uint8_t *buf, size_t buflen);
3030 static void client_process_message(struct tevent_req *req,
3031 uint8_t *buf, size_t buflen);
3032 static void client_process_control(struct tevent_req *req,
3033 uint8_t *buf, size_t buflen);
3034 static void client_reply_done(struct tevent_req *subreq);
3036 static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
3037 struct tevent_context *ev,
3038 int fd, struct ctdbd_context *ctdb,
3041 struct tevent_req *req;
3042 struct client_state *state;
3044 socklen_t crl = sizeof(struct ucred);
3047 req = tevent_req_create(mem_ctx, &state, struct client_state);
3057 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
3059 tevent_req_error(req, ret);
3060 return tevent_req_post(req, ev);
3062 state->pid = cr.pid;
3064 ret = comm_setup(state, ev, fd, client_read_handler, req,
3065 client_dead_handler, req, &state->comm);
3067 tevent_req_error(req, ret);
3068 return tevent_req_post(req, ev);
3071 ret = client_add(ctdb, state->pid, state);
3073 tevent_req_error(req, ret);
3074 return tevent_req_post(req, ev);
3077 DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
3082 static void client_read_handler(uint8_t *buf, size_t buflen,
3085 struct tevent_req *req = talloc_get_type_abort(
3086 private_data, struct tevent_req);
3087 struct client_state *state = tevent_req_data(
3088 req, struct client_state);
3089 struct ctdbd_context *ctdb = state->ctdb;
3090 struct ctdb_req_header header;
3094 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3099 if (buflen != header.length) {
3103 ret = ctdb_req_header_verify(&header, 0);
3108 header_fix_pnn(&header, ctdb);
3110 if (header.destnode == CTDB_BROADCAST_ALL) {
3111 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3112 header.destnode = i;
3114 ctdb_req_header_push(&header, buf, &np);
3115 client_process_packet(req, buf, buflen);
3120 if (header.destnode == CTDB_BROADCAST_CONNECTED) {
3121 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3122 if (ctdb->node_map->node[i].flags &
3123 NODE_FLAGS_DISCONNECTED) {
3127 header.destnode = i;
3129 ctdb_req_header_push(&header, buf, &np);
3130 client_process_packet(req, buf, buflen);
3135 if (header.destnode > ctdb->node_map->num_nodes) {
3136 fprintf(stderr, "Invalid destination pnn 0x%x\n",
3142 if (ctdb->node_map->node[header.destnode].flags & NODE_FLAGS_DISCONNECTED) {
3143 fprintf(stderr, "Packet for disconnected node pnn %u\n",
3148 ctdb_req_header_push(&header, buf, &np);
3149 client_process_packet(req, buf, buflen);
3152 static void client_dead_handler(void *private_data)
3154 struct tevent_req *req = talloc_get_type_abort(
3155 private_data, struct tevent_req);
3157 tevent_req_done(req);
3160 static void client_process_packet(struct tevent_req *req,
3161 uint8_t *buf, size_t buflen)
3163 struct ctdb_req_header header;
3167 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3172 switch (header.operation) {
3173 case CTDB_REQ_MESSAGE:
3174 client_process_message(req, buf, buflen);
3177 case CTDB_REQ_CONTROL:
3178 client_process_control(req, buf, buflen);
3186 static void client_process_message(struct tevent_req *req,
3187 uint8_t *buf, size_t buflen)
3189 struct client_state *state = tevent_req_data(
3190 req, struct client_state);
3191 struct ctdbd_context *ctdb = state->ctdb;
3192 TALLOC_CTX *mem_ctx;
3193 struct ctdb_req_header header;
3194 struct ctdb_req_message request;
3198 mem_ctx = talloc_new(state);
3199 if (tevent_req_nomem(mem_ctx, req)) {
3203 ret = ctdb_req_message_pull(buf, buflen, &header, mem_ctx, &request);
3205 talloc_free(mem_ctx);
3206 tevent_req_error(req, ret);
3210 header_fix_pnn(&header, ctdb);
3212 if (header.destnode >= ctdb->node_map->num_nodes) {
3213 /* Many messages are not replied to, so just behave as
3214 * though this message was not received */
3215 fprintf(stderr, "Invalid node %d\n", header.destnode);
3216 talloc_free(mem_ctx);
3220 srvid = request.srvid;
3221 DEBUG(DEBUG_INFO, ("request srvid = 0x%"PRIx64"\n", srvid));
3223 if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
3224 message_disable_recoveries(mem_ctx, req, &header, &request);
3225 } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
3226 message_takeover_run(mem_ctx, req, &header, &request);
3230 talloc_free(mem_ctx);
3233 static void client_process_control(struct tevent_req *req,
3234 uint8_t *buf, size_t buflen)
3236 struct client_state *state = tevent_req_data(
3237 req, struct client_state);
3238 struct ctdbd_context *ctdb = state->ctdb;
3239 TALLOC_CTX *mem_ctx;
3240 struct ctdb_req_header header;
3241 struct ctdb_req_control request;
3244 mem_ctx = talloc_new(state);
3245 if (tevent_req_nomem(mem_ctx, req)) {
3249 ret = ctdb_req_control_pull(buf, buflen, &header, mem_ctx, &request);
3251 talloc_free(mem_ctx);
3252 tevent_req_error(req, ret);
3256 header_fix_pnn(&header, ctdb);
3258 if (header.destnode >= ctdb->node_map->num_nodes) {
3259 struct ctdb_reply_control reply;
3261 reply.rdata.opcode = request.opcode;
3262 reply.errmsg = "Invalid node";
3264 client_send_control(req, &header, &reply);
3268 DEBUG(DEBUG_INFO, ("request opcode = %u, reqid = %u\n",
3269 request.opcode, header.reqid));
3271 if (fake_control_failure(mem_ctx, req, &header, &request)) {
3275 switch (request.opcode) {
3276 case CTDB_CONTROL_PROCESS_EXISTS:
3277 control_process_exists(mem_ctx, req, &header, &request);
3280 case CTDB_CONTROL_PING:
3281 control_ping(mem_ctx, req, &header, &request);
3284 case CTDB_CONTROL_GETDBPATH:
3285 control_getdbpath(mem_ctx, req, &header, &request);
3288 case CTDB_CONTROL_GETVNNMAP:
3289 control_getvnnmap(mem_ctx, req, &header, &request);
3292 case CTDB_CONTROL_GET_DEBUG:
3293 control_get_debug(mem_ctx, req, &header, &request);
3296 case CTDB_CONTROL_SET_DEBUG:
3297 control_set_debug(mem_ctx, req, &header, &request);
3300 case CTDB_CONTROL_GET_DBMAP:
3301 control_get_dbmap(mem_ctx, req, &header, &request);
3304 case CTDB_CONTROL_GET_RECMODE:
3305 control_get_recmode(mem_ctx, req, &header, &request);
3308 case CTDB_CONTROL_SET_RECMODE:
3309 control_set_recmode(mem_ctx, req, &header, &request);
3312 case CTDB_CONTROL_REGISTER_SRVID:
3313 control_register_srvid(mem_ctx, req, &header, &request);
3316 case CTDB_CONTROL_DEREGISTER_SRVID:
3317 control_deregister_srvid(mem_ctx, req, &header, &request);
3320 case CTDB_CONTROL_GET_DBNAME:
3321 control_get_dbname(mem_ctx, req, &header, &request);
3324 case CTDB_CONTROL_GET_PID:
3325 control_get_pid(mem_ctx, req, &header, &request);
3328 case CTDB_CONTROL_GET_RECMASTER:
3329 control_get_recmaster(mem_ctx, req, &header, &request);
3332 case CTDB_CONTROL_GET_PNN:
3333 control_get_pnn(mem_ctx, req, &header, &request);
3336 case CTDB_CONTROL_SHUTDOWN:
3337 control_shutdown(mem_ctx, req, &header, &request);
3340 case CTDB_CONTROL_SET_TUNABLE:
3341 control_set_tunable(mem_ctx, req, &header, &request);
3344 case CTDB_CONTROL_GET_TUNABLE:
3345 control_get_tunable(mem_ctx, req, &header, &request);
3348 case CTDB_CONTROL_LIST_TUNABLES:
3349 control_list_tunables(mem_ctx, req, &header, &request);
3352 case CTDB_CONTROL_MODIFY_FLAGS:
3353 control_modify_flags(mem_ctx, req, &header, &request);
3356 case CTDB_CONTROL_GET_ALL_TUNABLES:
3357 control_get_all_tunables(mem_ctx, req, &header, &request);
3360 case CTDB_CONTROL_UPTIME:
3361 control_uptime(mem_ctx, req, &header, &request);
3364 case CTDB_CONTROL_RELOAD_NODES_FILE:
3365 control_reload_nodes_file(mem_ctx, req, &header, &request);
3368 case CTDB_CONTROL_GET_CAPABILITIES:
3369 control_get_capabilities(mem_ctx, req, &header, &request);
3372 case CTDB_CONTROL_RELEASE_IP:
3373 control_release_ip(mem_ctx, req, &header, &request);
3376 case CTDB_CONTROL_TAKEOVER_IP:
3377 control_takeover_ip(mem_ctx, req, &header, &request);
3380 case CTDB_CONTROL_GET_PUBLIC_IPS:
3381 control_get_public_ips(mem_ctx, req, &header, &request);
3384 case CTDB_CONTROL_GET_NODEMAP:
3385 control_get_nodemap(mem_ctx, req, &header, &request);
3388 case CTDB_CONTROL_GET_RECLOCK_FILE:
3389 control_get_reclock_file(mem_ctx, req, &header, &request);
3392 case CTDB_CONTROL_STOP_NODE:
3393 control_stop_node(mem_ctx, req, &header, &request);
3396 case CTDB_CONTROL_CONTINUE_NODE:
3397 control_continue_node(mem_ctx, req, &header, &request);
3400 case CTDB_CONTROL_SET_BAN_STATE:
3401 control_set_ban_state(mem_ctx, req, &header, &request);
3404 case CTDB_CONTROL_GET_DB_SEQNUM:
3405 control_get_db_seqnum(mem_ctx, req, &header, &request);
3408 case CTDB_CONTROL_DB_GET_HEALTH:
3409 control_db_get_health(mem_ctx, req, &header, &request);
3412 case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
3413 control_get_public_ip_info(mem_ctx, req, &header, &request);
3416 case CTDB_CONTROL_GET_IFACES:
3417 control_get_ifaces(mem_ctx, req, &header, &request);
3420 case CTDB_CONTROL_SET_IFACE_LINK_STATE:
3421 control_set_iface_link_state(mem_ctx, req, &header, &request);
3424 case CTDB_CONTROL_SET_DB_READONLY:
3425 control_set_db_readonly(mem_ctx, req, &header, &request);
3428 case CTDB_CONTROL_SET_DB_STICKY:
3429 control_set_db_sticky(mem_ctx, req, &header, &request);
3432 case CTDB_CONTROL_IPREALLOCATED:
3433 control_ipreallocated(mem_ctx, req, &header, &request);
3436 case CTDB_CONTROL_GET_RUNSTATE:
3437 control_get_runstate(mem_ctx, req, &header, &request);
3440 case CTDB_CONTROL_GET_NODES_FILE:
3441 control_get_nodes_file(mem_ctx, req, &header, &request);
3444 case CTDB_CONTROL_CHECK_PID_SRVID:
3445 control_check_pid_srvid(mem_ctx, req, &header, &request);
3449 if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) {
3450 control_error(mem_ctx, req, &header, &request);
3456 talloc_free(mem_ctx);
3459 static int client_recv(struct tevent_req *req, int *perr)
3461 struct client_state *state = tevent_req_data(
3462 req, struct client_state);
3465 DEBUG(DEBUG_INFO, ("Client done fd=%d\n", state->fd));
3468 if (tevent_req_is_unix_error(req, &err)) {
3475 return state->status;
3482 struct server_state {
3483 struct tevent_context *ev;
3484 struct ctdbd_context *ctdb;
3488 static void server_new_client(struct tevent_req *subreq);
3489 static void server_client_done(struct tevent_req *subreq);
3491 static struct tevent_req *server_send(TALLOC_CTX *mem_ctx,
3492 struct tevent_context *ev,
3493 struct ctdbd_context *ctdb,
3496 struct tevent_req *req, *subreq;
3497 struct server_state *state;
3499 req = tevent_req_create(mem_ctx, &state, struct server_state);
3508 subreq = accept_send(state, ev, fd);
3509 if (tevent_req_nomem(subreq, req)) {
3510 return tevent_req_post(req, ev);
3512 tevent_req_set_callback(subreq, server_new_client, req);
3517 static void server_new_client(struct tevent_req *subreq)
3519 struct tevent_req *req = tevent_req_callback_data(
3520 subreq, struct tevent_req);
3521 struct server_state *state = tevent_req_data(
3522 req, struct server_state);
3523 struct ctdbd_context *ctdb = state->ctdb;
3527 client_fd = accept_recv(subreq, NULL, NULL, &ret);
3528 TALLOC_FREE(subreq);
3529 if (client_fd == -1) {
3530 tevent_req_error(req, ret);
3534 subreq = client_send(state, state->ev, client_fd,
3535 ctdb, ctdb->node_map->pnn);
3536 if (tevent_req_nomem(subreq, req)) {
3539 tevent_req_set_callback(subreq, server_client_done, req);
3541 ctdb->num_clients += 1;
3543 subreq = accept_send(state, state->ev, state->fd);
3544 if (tevent_req_nomem(subreq, req)) {
3547 tevent_req_set_callback(subreq, server_new_client, req);
3550 static void server_client_done(struct tevent_req *subreq)
3552 struct tevent_req *req = tevent_req_callback_data(
3553 subreq, struct tevent_req);
3554 struct server_state *state = tevent_req_data(
3555 req, struct server_state);
3556 struct ctdbd_context *ctdb = state->ctdb;
3560 status = client_recv(subreq, &ret);
3561 TALLOC_FREE(subreq);
3563 tevent_req_error(req, ret);
3567 ctdb->num_clients -= 1;
3570 /* Special status, to shutdown server */
3571 DEBUG(DEBUG_INFO, ("Shutting down server\n"));
3572 tevent_req_done(req);
3576 static bool server_recv(struct tevent_req *req, int *perr)
3580 if (tevent_req_is_unix_error(req, &err)) {
3593 static int socket_init(const char *sockpath)
3595 struct sockaddr_un addr;
3599 memset(&addr, 0, sizeof(addr));
3600 addr.sun_family = AF_UNIX;
3602 len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
3603 if (len >= sizeof(addr.sun_path)) {
3604 fprintf(stderr, "path too long: %s\n", sockpath);
3608 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3610 fprintf(stderr, "socket failed - %s\n", sockpath);
3614 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
3616 fprintf(stderr, "bind failed - %s\n", sockpath);
3620 ret = listen(fd, 10);
3622 fprintf(stderr, "listen failed\n");
3626 DEBUG(DEBUG_INFO, ("Socket init done\n"));
3637 static struct options {
3638 const char *sockpath;
3639 const char *pidfile;
3640 const char *debuglevel;
3643 static struct poptOption cmdline_options[] = {
3644 { "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
3645 "Unix domain socket path", "filename" },
3646 { "pidfile", 'p', POPT_ARG_STRING, &options.pidfile, 0,
3647 "pid file", "filename" } ,
3648 { "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
3649 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
3652 static void cleanup(void)
3654 unlink(options.sockpath);
3655 unlink(options.pidfile);
3658 static void signal_handler(int sig)
3664 static void start_server(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3665 struct ctdbd_context *ctdb, int fd, int pfd)
3667 struct tevent_req *req;
3672 signal(SIGTERM, signal_handler);
3674 req = server_send(mem_ctx, ev, ctdb, fd);
3676 fprintf(stderr, "Memory error\n");
3680 len = write(pfd, &ret, sizeof(ret));
3681 if (len != sizeof(ret)) {
3682 fprintf(stderr, "Failed to send message to parent\n");
3687 tevent_req_poll(req, ev);
3689 server_recv(req, &ret);
3695 int main(int argc, const char *argv[])
3697 TALLOC_CTX *mem_ctx;
3698 struct ctdbd_context *ctdb;
3699 struct tevent_context *ev;
3701 int opt, fd, ret, pfd[2];
3706 pc = poptGetContext(argv[0], argc, argv, cmdline_options,
3707 POPT_CONTEXT_KEEP_FIRST);
3708 while ((opt = poptGetNextOpt(pc)) != -1) {
3709 fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
3713 if (options.sockpath == NULL) {
3714 fprintf(stderr, "Please specify socket path\n");
3715 poptPrintHelp(pc, stdout, 0);
3719 if (options.pidfile == NULL) {
3720 fprintf(stderr, "Please specify pid file\n");
3721 poptPrintHelp(pc, stdout, 0);
3725 mem_ctx = talloc_new(NULL);
3726 if (mem_ctx == NULL) {
3727 fprintf(stderr, "Memory error\n");
3731 ret = logging_init(mem_ctx, "file:", options.debuglevel, "fake-ctdbd");
3733 fprintf(stderr, "Invalid debug level\n");
3734 poptPrintHelp(pc, stdout, 0);
3738 ctdb = ctdbd_setup(mem_ctx);
3743 if (! ctdbd_verify(ctdb)) {
3747 ev = tevent_context_init(mem_ctx);
3749 fprintf(stderr, "Memory error\n");
3753 fd = socket_init(options.sockpath);
3760 fprintf(stderr, "Failed to create pipe\n");
3767 fprintf(stderr, "Failed to fork\n");
3775 start_server(mem_ctx, ev, ctdb, fd, pfd[1]);
3782 len = read(pfd[0], &ret, sizeof(ret));
3784 if (len != sizeof(ret)) {
3785 fprintf(stderr, "len = %zi\n", len);
3786 fprintf(stderr, "Failed to get message from child\n");
3791 fp = fopen(options.pidfile, "w");
3793 fprintf(stderr, "Failed to open pid file %s\n",
3798 fprintf(fp, "%d\n", pid);