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/system.h"
41 #include "common/logging.h"
42 #include "common/tunable.h"
43 #include "common/srvid.h"
45 #include "ipalloc_read_known_ips.h"
48 #define CTDB_PORT 4379
50 /* A fake flag that is only supported by some functions */
51 #define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
57 uint32_t capabilities;
58 bool recovery_disabled;
59 void *recovery_substate;
75 struct interface_map {
77 struct interface *iface;
99 struct fake_control_failure {
100 struct fake_control_failure *prev, *next;
101 enum ctdb_controls opcode;
108 struct ctdb_client *prev, *next;
109 struct ctdbd_context *ctdb;
114 struct ctdbd_context {
115 struct node_map *node_map;
116 struct interface_map *iface_map;
117 struct vnn_map *vnn_map;
118 struct database_map *db_map;
119 struct srvid_context *srv;
121 struct timeval start_time;
122 struct timeval recovery_start_time;
123 struct timeval recovery_end_time;
124 bool takeover_disabled;
126 enum ctdb_runstate runstate;
127 struct ctdb_tunable_list tun_list;
129 struct ctdb_public_ip_list *known_ips;
130 struct fake_control_failure *control_failures;
131 struct ctdb_client *client_list;
138 static struct node_map *nodemap_init(TALLOC_CTX *mem_ctx)
140 struct node_map *node_map;
142 node_map = talloc_zero(mem_ctx, struct node_map);
143 if (node_map == NULL) {
147 node_map->pnn = CTDB_UNKNOWN_PNN;
148 node_map->recmaster = CTDB_UNKNOWN_PNN;
153 /* Read a nodemap from stdin. Each line looks like:
154 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
155 * EOF or a blank line terminates input.
157 * By default, capablities for each node are
158 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER. These 2
159 * capabilities can be faked off by adding, for example,
160 * -CTDB_CAP_RECMASTER.
163 static bool nodemap_parse(struct node_map *node_map)
167 while ((fgets(line, sizeof(line), stdin) != NULL)) {
168 uint32_t pnn, flags, capabilities;
171 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 if (!parse_ip(tok, NULL, CTDB_PORT, &saddr)) {
198 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
201 ip = talloc_strdup(node_map, tok);
207 tok = strtok(NULL, " \t");
209 fprintf(stderr, "bad line (%s) - missing flags\n",
213 flags = (uint32_t)strtoul(tok, NULL, 0);
214 /* Handle deleted nodes */
215 if (flags & NODE_FLAGS_DELETED) {
217 ip = talloc_strdup(node_map, "0.0.0.0");
222 capabilities = CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER;
224 tok = strtok(NULL, " \t");
225 while (tok != NULL) {
226 if (strcmp(tok, "CURRENT") == 0) {
228 } else if (strcmp(tok, "RECMASTER") == 0) {
229 node_map->recmaster = pnn;
230 } else if (strcmp(tok, "-CTDB_CAP_RECMASTER") == 0) {
231 capabilities &= ~CTDB_CAP_RECMASTER;
232 } else if (strcmp(tok, "-CTDB_CAP_LMASTER") == 0) {
233 capabilities &= ~CTDB_CAP_LMASTER;
234 } else if (strcmp(tok, "TIMEOUT") == 0) {
235 /* This can be done with just a flag
236 * value but it is probably clearer
237 * and less error-prone to fake this
238 * with an explicit token */
239 flags |= NODE_FLAGS_FAKE_TIMEOUT;
241 tok = strtok(NULL, " \t");
244 node_map->node = talloc_realloc(node_map, node_map->node,
246 node_map->num_nodes + 1);
247 if (node_map->node == NULL) {
250 node = &node_map->node[node_map->num_nodes];
252 parse_ip(ip, NULL, CTDB_PORT, &node->addr);
255 node->capabilities = capabilities;
256 node->recovery_disabled = false;
257 node->recovery_substate = NULL;
259 node_map->num_nodes += 1;
262 DEBUG(DEBUG_INFO, ("Parsing nodemap done\n"));
266 DEBUG(DEBUG_INFO, ("Parsing nodemap failed\n"));
271 /* Append a node to a node map with given address and flags */
272 static bool node_map_add(struct ctdb_node_map *nodemap,
273 const char *nstr, uint32_t flags)
277 struct ctdb_node_and_flags *n;
279 if (! parse_ip(nstr, NULL, CTDB_PORT, &addr)) {
280 fprintf(stderr, "Invalid IP address %s\n", nstr);
285 nodemap->node = talloc_realloc(nodemap, nodemap->node,
286 struct ctdb_node_and_flags, num+1);
287 if (nodemap->node == NULL) {
291 n = &nodemap->node[num];
296 nodemap->num = num+1;
300 /* Read a nodes file into a node map */
301 static struct ctdb_node_map *ctdb_read_nodes_file(TALLOC_CTX *mem_ctx,
307 struct ctdb_node_map *nodemap;
309 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
310 if (nodemap == NULL) {
314 lines = file_lines_load(nlist, &nlines, 0, mem_ctx);
319 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
323 for (i=0; i<nlines; i++) {
329 /* strip leading spaces */
330 while((*node == ' ') || (*node == '\t')) {
336 /* strip trailing spaces */
338 ((node[len-1] == ' ') || (node[len-1] == '\t')))
348 /* A "deleted" node is a node that is
349 commented out in the nodes file. This is
350 used instead of removing a line, which
351 would cause subsequent nodes to change
353 flags = NODE_FLAGS_DELETED;
354 node = discard_const("0.0.0.0");
358 if (! node_map_add(nodemap, node, flags)) {
360 TALLOC_FREE(nodemap);
369 static struct ctdb_node_map *read_nodes_file(TALLOC_CTX *mem_ctx,
372 struct ctdb_node_map *nodemap;
373 char nodepath[PATH_MAX];
374 const char *nodes_list;
376 /* read the nodes file */
377 sprintf(nodepath, "CTDB_NODES_%u", pnn);
378 nodes_list = getenv(nodepath);
379 if (nodes_list == NULL) {
380 nodes_list = getenv("CTDB_NODES");
381 if (nodes_list == NULL) {
382 DEBUG(DEBUG_INFO, ("Nodes file not defined\n"));
387 nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
388 if (nodemap == NULL) {
389 DEBUG(DEBUG_INFO, ("Failed to read nodes file \"%s\"\n",
397 static struct interface_map *interfaces_init(TALLOC_CTX *mem_ctx)
399 struct interface_map *iface_map;
401 iface_map = talloc_zero(mem_ctx, struct interface_map);
402 if (iface_map == NULL) {
409 /* Read interfaces information. Same format as "ctdb ifaces -Y"
411 * :Name:LinkStatus:References:
416 static bool interfaces_parse(struct interface_map *iface_map)
420 while ((fgets(line, sizeof(line), stdin) != NULL)) {
423 char *tok, *t, *name;
424 struct interface *iface;
426 if (line[0] == '\n') {
430 /* Get rid of pesky newline */
431 if ((t = strchr(line, '\n')) != NULL) {
435 if (strcmp(line, ":Name:LinkStatus:References:") == 0) {
439 /* Leading colon... */
440 // tok = strtok(line, ":");
443 tok = strtok(line, ":");
445 fprintf(stderr, "bad line (%s) - missing name\n", line);
451 tok = strtok(NULL, ":");
453 fprintf(stderr, "bad line (%s) - missing link state\n",
457 link_state = (uint16_t)strtoul(tok, NULL, 0);
460 tok = strtok(NULL, ":");
462 fprintf(stderr, "bad line (%s) - missing references\n",
466 references = (uint32_t)strtoul(tok, NULL, 0);
468 iface_map->iface = talloc_realloc(iface_map, iface_map->iface,
471 if (iface_map->iface == NULL) {
475 iface = &iface_map->iface[iface_map->num];
477 iface->name = talloc_strdup(iface_map, name);
478 if (iface->name == NULL) {
481 iface->link_up = link_state;
482 iface->references = references;
487 DEBUG(DEBUG_INFO, ("Parsing interfaces done\n"));
491 fprintf(stderr, "Parsing interfaces failed\n");
495 static struct vnn_map *vnnmap_init(TALLOC_CTX *mem_ctx)
497 struct vnn_map *vnn_map;
499 vnn_map = talloc_zero(mem_ctx, struct vnn_map);
500 if (vnn_map == NULL) {
501 fprintf(stderr, "Memory error\n");
504 vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
505 vnn_map->generation = INVALID_GENERATION;
518 static bool vnnmap_parse(struct vnn_map *vnn_map)
522 while (fgets(line, sizeof(line), stdin) != NULL) {
526 if (line[0] == '\n') {
530 /* Get rid of pesky newline */
531 if ((t = strchr(line, '\n')) != NULL) {
535 n = (uint32_t) strtol(line, NULL, 0);
538 if (vnn_map->generation == INVALID_GENERATION) {
539 vnn_map->generation = n;
543 vnn_map->map = talloc_realloc(vnn_map, vnn_map->map, uint32_t,
545 if (vnn_map->map == NULL) {
546 fprintf(stderr, "Memory error\n");
550 vnn_map->map[vnn_map->size] = n;
554 DEBUG(DEBUG_INFO, ("Parsing vnnmap done\n"));
558 fprintf(stderr, "Parsing vnnmap failed\n");
562 static bool reclock_parse(struct ctdbd_context *ctdb)
567 if (fgets(line, sizeof(line), stdin) == NULL) {
571 if (line[0] == '\n') {
572 /* Recovery lock remains unset */
576 /* Get rid of pesky newline */
577 if ((t = strchr(line, '\n')) != NULL) {
581 ctdb->reclock = talloc_strdup(ctdb, line);
582 if (ctdb->reclock == NULL) {
586 /* Swallow possible blank line following section. Picky
587 * compiler settings don't allow the return value to be
588 * ignored, so make the compiler happy.
590 if (fgets(line, sizeof(line), stdin) == NULL) {
593 DEBUG(DEBUG_INFO, ("Parsing reclock done\n"));
597 fprintf(stderr, "Parsing reclock failed\n");
601 static struct database_map *dbmap_init(TALLOC_CTX *mem_ctx)
603 struct database_map *db_map;
605 db_map = talloc_zero(mem_ctx, struct database_map);
606 if (db_map == NULL) {
613 /* Read a database map from stdin. Each line looks like:
614 * <ID> <NAME> [FLAGS] [SEQ_NUM]
615 * EOF or a blank line terminates input.
617 * By default, flags and seq_num are 0
620 static bool dbmap_parse(struct database_map *db_map)
624 while ((fgets(line, sizeof(line), stdin) != NULL)) {
627 uint32_t seq_num = 0;
632 if (line[0] == '\n') {
636 /* Get rid of pesky newline */
637 if ((t = strchr(line, '\n')) != NULL) {
642 tok = strtok(line, " \t");
644 fprintf(stderr, "bad line (%s) - missing ID\n", line);
647 id = (uint32_t)strtoul(tok, NULL, 0);
650 tok = strtok(NULL, " \t");
652 fprintf(stderr, "bad line (%s) - missing NAME\n", line);
655 name = talloc_strdup(db_map, tok);
661 tok = strtok(NULL, " \t");
662 while (tok != NULL) {
663 if (strcmp(tok, "PERSISTENT") == 0) {
664 flags |= CTDB_DB_FLAGS_PERSISTENT;
665 } else if (strcmp(tok, "STICKY") == 0) {
666 flags |= CTDB_DB_FLAGS_STICKY;
667 } else if (strcmp(tok, "READONLY") == 0) {
668 flags |= CTDB_DB_FLAGS_READONLY;
669 } else if (strcmp(tok, "REPLICATED") == 0) {
670 flags |= CTDB_DB_FLAGS_REPLICATED;
671 } else if (tok[0] >= '0'&& tok[0] <= '9') {
672 uint8_t nv = CTDB_DB_FLAGS_PERSISTENT |
673 CTDB_DB_FLAGS_REPLICATED;
675 if ((flags & nv) == 0) {
677 "seq_num for volatile db\n");
680 seq_num = (uint64_t)strtoull(tok, NULL, 0);
683 tok = strtok(NULL, " \t");
686 db_map->db = talloc_realloc(db_map, db_map->db,
688 db_map->num_dbs + 1);
689 if (db_map->db == NULL) {
692 db = &db_map->db[db_map->num_dbs];
697 db->seq_num = seq_num;
699 db_map->num_dbs += 1;
702 DEBUG(DEBUG_INFO, ("Parsing dbmap done\n"));
706 DEBUG(DEBUG_INFO, ("Parsing dbmap failed\n"));
711 static struct database *database_find(struct database_map *map,
716 for (i = 0; i < map->num_dbs; i++) {
717 struct database *db = &map->db[i];
719 if (db->id == db_id) {
727 static bool public_ips_parse(struct ctdbd_context *ctdb,
731 D_ERR("Must initialise nodemap before public IPs\n");
735 ctdb->known_ips = ipalloc_read_known_ips(ctdb, numnodes, false);
737 return (ctdb->known_ips != NULL);
740 /* Read information about controls to fail. Format is:
741 * <opcode> <pnn> {ERROR|TIMEOUT} <comment>
743 static bool control_failures_parse(struct ctdbd_context *ctdb)
747 while ((fgets(line, sizeof(line), stdin) != NULL)) {
749 enum ctdb_controls opcode;
753 struct fake_control_failure *failure = NULL;
755 if (line[0] == '\n') {
759 /* Get rid of pesky newline */
760 if ((t = strchr(line, '\n')) != NULL) {
765 tok = strtok(line, " \t");
767 D_ERR("bad line (%s) - missing opcode\n", line);
770 opcode = (enum ctdb_controls)strtoul(tok, NULL, 0);
773 tok = strtok(NULL, " \t");
775 D_ERR("bad line (%s) - missing PNN\n", line);
778 pnn = (uint32_t)strtoul(tok, NULL, 0);
781 tok = strtok(NULL, " \t");
783 D_ERR("bad line (%s) - missing errno\n", line);
786 error = talloc_strdup(ctdb, tok);
790 if (strcmp(error, "ERROR") != 0 &&
791 strcmp(error, "TIMEOUT") != 0) {
792 D_ERR("bad line (%s) "
793 "- error must be \"ERROR\" or \"TIMEOUT\"\n",
799 tok = strtok(NULL, "\n"); /* rest of line */
801 D_ERR("bad line (%s) - missing comment\n", line);
804 comment = talloc_strdup(ctdb, tok);
805 if (comment == NULL) {
809 failure = talloc_zero(ctdb, struct fake_control_failure);
810 if (failure == NULL) {
814 failure->opcode = opcode;
816 failure->error = error;
817 failure->comment = comment;
819 DLIST_ADD(ctdb->control_failures, failure);
822 D_INFO("Parsing fake control failures done\n");
826 D_INFO("Parsing fake control failures failed\n");
834 static int ctdb_client_destructor(struct ctdb_client *client)
836 DLIST_REMOVE(client->ctdb->client_list, client);
840 static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
843 struct ctdb_client *client;
845 client = talloc_zero(client_state, struct ctdb_client);
846 if (client == NULL) {
851 client->pid = client_pid;
852 client->state = client_state;
854 DLIST_ADD(ctdb->client_list, client);
855 talloc_set_destructor(client, ctdb_client_destructor);
859 static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
861 struct ctdb_client *client;
863 for (client=ctdb->client_list; client != NULL; client=client->next) {
864 if (client->pid == client_pid) {
865 return client->state;
876 static uint32_t new_generation(uint32_t old_generation)
881 generation = random();
882 if (generation != INVALID_GENERATION &&
883 generation != old_generation) {
891 static struct ctdbd_context *ctdbd_setup(TALLOC_CTX *mem_ctx)
893 struct ctdbd_context *ctdb;
898 ctdb = talloc_zero(mem_ctx, struct ctdbd_context);
903 ctdb->node_map = nodemap_init(ctdb);
904 if (ctdb->node_map == NULL) {
908 ctdb->iface_map = interfaces_init(ctdb);
909 if (ctdb->iface_map == NULL) {
913 ctdb->vnn_map = vnnmap_init(ctdb);
914 if (ctdb->vnn_map == NULL) {
918 ctdb->db_map = dbmap_init(ctdb);
919 if (ctdb->db_map == NULL) {
923 ret = srvid_init(ctdb, &ctdb->srv);
928 while (fgets(line, sizeof(line), stdin) != NULL) {
931 if ((t = strchr(line, '\n')) != NULL) {
935 if (strcmp(line, "NODEMAP") == 0) {
936 status = nodemap_parse(ctdb->node_map);
937 } else if (strcmp(line, "IFACES") == 0) {
938 status = interfaces_parse(ctdb->iface_map);
939 } else if (strcmp(line, "VNNMAP") == 0) {
940 status = vnnmap_parse(ctdb->vnn_map);
941 } else if (strcmp(line, "DBMAP") == 0) {
942 status = dbmap_parse(ctdb->db_map);
943 } else if (strcmp(line, "PUBLICIPS") == 0) {
944 status = public_ips_parse(ctdb,
945 ctdb->node_map->num_nodes);
946 } else if (strcmp(line, "RECLOCK") == 0) {
947 status = reclock_parse(ctdb);
948 } else if (strcmp(line, "CONTROLFAILS") == 0) {
949 status = control_failures_parse(ctdb);
951 fprintf(stderr, "Unknown line %s\n", line);
960 ctdb->start_time = tevent_timeval_current();
961 ctdb->recovery_start_time = tevent_timeval_current();
962 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
963 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
964 ctdb->vnn_map->generation =
965 new_generation(ctdb->vnn_map->generation);
967 ctdb->recovery_end_time = tevent_timeval_current();
969 ctdb->log_level = DEBUG_ERR;
970 ctdb->runstate = CTDB_RUNSTATE_RUNNING;
972 ctdb_tunable_set_defaults(&ctdb->tun_list);
981 static bool ctdbd_verify(struct ctdbd_context *ctdb)
986 if (ctdb->node_map->num_nodes == 0) {
990 /* Make sure all the nodes are in order */
991 for (i=0; i<ctdb->node_map->num_nodes; i++) {
992 node = &ctdb->node_map->node[i];
993 if (node->pnn != i) {
994 fprintf(stderr, "Expected node %u, found %u\n",
1000 node = &ctdb->node_map->node[ctdb->node_map->pnn];
1001 if (node->flags & NODE_FLAGS_DISCONNECTED) {
1002 DEBUG(DEBUG_INFO, ("Node disconnected, exiting\n"));
1013 struct recover_state {
1014 struct tevent_context *ev;
1015 struct ctdbd_context *ctdb;
1018 static int recover_check(struct tevent_req *req);
1019 static void recover_wait_done(struct tevent_req *subreq);
1020 static void recover_done(struct tevent_req *subreq);
1022 static struct tevent_req *recover_send(TALLOC_CTX *mem_ctx,
1023 struct tevent_context *ev,
1024 struct ctdbd_context *ctdb)
1026 struct tevent_req *req;
1027 struct recover_state *state;
1030 req = tevent_req_create(mem_ctx, &state, struct recover_state);
1038 ret = recover_check(req);
1040 tevent_req_error(req, ret);
1041 return tevent_req_post(req, ev);
1047 static int recover_check(struct tevent_req *req)
1049 struct recover_state *state = tevent_req_data(
1050 req, struct recover_state);
1051 struct ctdbd_context *ctdb = state->ctdb;
1052 struct tevent_req *subreq;
1053 bool recovery_disabled;
1056 recovery_disabled = false;
1057 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1058 if (ctdb->node_map->node[i].recovery_disabled) {
1059 recovery_disabled = true;
1064 subreq = tevent_wakeup_send(state, state->ev,
1065 tevent_timeval_current_ofs(1, 0));
1066 if (subreq == NULL) {
1070 if (recovery_disabled) {
1071 tevent_req_set_callback(subreq, recover_wait_done, req);
1073 ctdb->recovery_start_time = tevent_timeval_current();
1074 tevent_req_set_callback(subreq, recover_done, req);
1080 static void recover_wait_done(struct tevent_req *subreq)
1082 struct tevent_req *req = tevent_req_callback_data(
1083 subreq, struct tevent_req);
1087 status = tevent_wakeup_recv(subreq);
1088 TALLOC_FREE(subreq);
1090 tevent_req_error(req, EIO);
1094 ret = recover_check(req);
1096 tevent_req_error(req, ret);
1100 static void recover_done(struct tevent_req *subreq)
1102 struct tevent_req *req = tevent_req_callback_data(
1103 subreq, struct tevent_req);
1104 struct recover_state *state = tevent_req_data(
1105 req, struct recover_state);
1106 struct ctdbd_context *ctdb = state->ctdb;
1109 status = tevent_wakeup_recv(subreq);
1110 TALLOC_FREE(subreq);
1112 tevent_req_error(req, EIO);
1116 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1117 ctdb->recovery_end_time = tevent_timeval_current();
1118 ctdb->vnn_map->generation = new_generation(ctdb->vnn_map->generation);
1120 tevent_req_done(req);
1123 static bool recover_recv(struct tevent_req *req, int *perr)
1127 if (tevent_req_is_unix_error(req, &err)) {
1138 * Routines for ctdb_req_header
1141 static void header_fix_pnn(struct ctdb_req_header *header,
1142 struct ctdbd_context *ctdb)
1144 if (header->srcnode == CTDB_CURRENT_NODE) {
1145 header->srcnode = ctdb->node_map->pnn;
1148 if (header->destnode == CTDB_CURRENT_NODE) {
1149 header->destnode = ctdb->node_map->pnn;
1153 static struct ctdb_req_header header_reply_control(
1154 struct ctdb_req_header *header,
1155 struct ctdbd_context *ctdb)
1157 struct ctdb_req_header reply_header;
1159 reply_header = (struct ctdb_req_header) {
1160 .ctdb_magic = CTDB_MAGIC,
1161 .ctdb_version = CTDB_PROTOCOL,
1162 .generation = ctdb->vnn_map->generation,
1163 .operation = CTDB_REPLY_CONTROL,
1164 .destnode = header->srcnode,
1165 .srcnode = header->destnode,
1166 .reqid = header->reqid,
1169 return reply_header;
1172 static struct ctdb_req_header header_reply_message(
1173 struct ctdb_req_header *header,
1174 struct ctdbd_context *ctdb)
1176 struct ctdb_req_header reply_header;
1178 reply_header = (struct ctdb_req_header) {
1179 .ctdb_magic = CTDB_MAGIC,
1180 .ctdb_version = CTDB_PROTOCOL,
1181 .generation = ctdb->vnn_map->generation,
1182 .operation = CTDB_REQ_MESSAGE,
1183 .destnode = header->srcnode,
1184 .srcnode = header->destnode,
1188 return reply_header;
1195 struct client_state {
1196 struct tevent_context *ev;
1198 struct ctdbd_context *ctdb;
1201 struct comm_context *comm;
1202 struct srvid_register_state *rstate;
1207 * Send replies to controls and messages
1210 static void client_reply_done(struct tevent_req *subreq);
1212 static void client_send_message(struct tevent_req *req,
1213 struct ctdb_req_header *header,
1214 struct ctdb_req_message_data *message)
1216 struct client_state *state = tevent_req_data(
1217 req, struct client_state);
1218 struct ctdbd_context *ctdb = state->ctdb;
1219 struct tevent_req *subreq;
1220 struct ctdb_req_header reply_header;
1222 size_t datalen, buflen;
1225 reply_header = header_reply_message(header, ctdb);
1227 datalen = ctdb_req_message_data_len(&reply_header, message);
1228 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1230 tevent_req_error(req, ret);
1234 ret = ctdb_req_message_data_push(&reply_header, message,
1237 tevent_req_error(req, ret);
1241 DEBUG(DEBUG_INFO, ("message srvid = 0x%"PRIx64"\n", message->srvid));
1243 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1244 if (tevent_req_nomem(subreq, req)) {
1247 tevent_req_set_callback(subreq, client_reply_done, req);
1249 talloc_steal(subreq, buf);
1252 static void client_send_control(struct tevent_req *req,
1253 struct ctdb_req_header *header,
1254 struct ctdb_reply_control *reply)
1256 struct client_state *state = tevent_req_data(
1257 req, struct client_state);
1258 struct ctdbd_context *ctdb = state->ctdb;
1259 struct tevent_req *subreq;
1260 struct ctdb_req_header reply_header;
1262 size_t datalen, buflen;
1265 reply_header = header_reply_control(header, ctdb);
1267 datalen = ctdb_reply_control_len(&reply_header, reply);
1268 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1270 tevent_req_error(req, ret);
1274 ret = ctdb_reply_control_push(&reply_header, reply, buf, &buflen);
1276 tevent_req_error(req, ret);
1280 DEBUG(DEBUG_INFO, ("reply opcode = %u\n", reply->rdata.opcode));
1282 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1283 if (tevent_req_nomem(subreq, req)) {
1286 tevent_req_set_callback(subreq, client_reply_done, req);
1288 talloc_steal(subreq, buf);
1291 static void client_reply_done(struct tevent_req *subreq)
1293 struct tevent_req *req = tevent_req_callback_data(
1294 subreq, struct tevent_req);
1298 status = comm_write_recv(subreq, &ret);
1299 TALLOC_FREE(subreq);
1301 tevent_req_error(req, ret);
1306 * Handling protocol - controls
1309 static void control_process_exists(TALLOC_CTX *mem_ctx,
1310 struct tevent_req *req,
1311 struct ctdb_req_header *header,
1312 struct ctdb_req_control *request)
1314 struct client_state *state = tevent_req_data(
1315 req, struct client_state);
1316 struct ctdbd_context *ctdb = state->ctdb;
1317 struct client_state *cstate;
1318 struct ctdb_reply_control reply;
1320 reply.rdata.opcode = request->opcode;
1322 cstate = client_find(ctdb, request->rdata.data.pid);
1323 if (cstate == NULL) {
1325 reply.errmsg = "No client for PID";
1327 reply.status = kill(request->rdata.data.pid, 0);
1328 reply.errmsg = NULL;
1331 client_send_control(req, header, &reply);
1334 static void control_ping(TALLOC_CTX *mem_ctx,
1335 struct tevent_req *req,
1336 struct ctdb_req_header *header,
1337 struct ctdb_req_control *request)
1339 struct client_state *state = tevent_req_data(
1340 req, struct client_state);
1341 struct ctdbd_context *ctdb = state->ctdb;
1342 struct ctdb_reply_control reply;
1344 reply.rdata.opcode = request->opcode;
1345 reply.status = ctdb->num_clients;
1346 reply.errmsg = NULL;
1348 client_send_control(req, header, &reply);
1351 static void control_getdbpath(TALLOC_CTX *mem_ctx,
1352 struct tevent_req *req,
1353 struct ctdb_req_header *header,
1354 struct ctdb_req_control *request)
1356 struct client_state *state = tevent_req_data(
1357 req, struct client_state);
1358 struct ctdbd_context *ctdb = state->ctdb;
1359 struct ctdb_reply_control reply;
1360 struct database *db;
1362 reply.rdata.opcode = request->opcode;
1364 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1366 reply.status = ENOENT;
1367 reply.errmsg = "Database not found";
1370 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
1371 base = "/var/lib/ctdb/persistent";
1373 base = "/var/run/ctdb/DB_DIR";
1375 reply.rdata.data.db_path =
1376 talloc_asprintf(mem_ctx, "%s/%s.%u",
1377 base, db->name, header->destnode);
1378 if (reply.rdata.data.db_path == NULL) {
1379 reply.status = ENOMEM;
1380 reply.errmsg = "Memory error";
1383 reply.errmsg = NULL;
1387 client_send_control(req, header, &reply);
1390 static void control_getvnnmap(TALLOC_CTX *mem_ctx,
1391 struct tevent_req *req,
1392 struct ctdb_req_header *header,
1393 struct ctdb_req_control *request)
1395 struct client_state *state = tevent_req_data(
1396 req, struct client_state);
1397 struct ctdbd_context *ctdb = state->ctdb;
1398 struct ctdb_reply_control reply;
1399 struct ctdb_vnn_map *vnnmap;
1401 reply.rdata.opcode = request->opcode;
1403 vnnmap = talloc_zero(mem_ctx, struct ctdb_vnn_map);
1404 if (vnnmap == NULL) {
1405 reply.status = ENOMEM;
1406 reply.errmsg = "Memory error";
1408 vnnmap->generation = ctdb->vnn_map->generation;
1409 vnnmap->size = ctdb->vnn_map->size;
1410 vnnmap->map = ctdb->vnn_map->map;
1412 reply.rdata.data.vnnmap = vnnmap;
1414 reply.errmsg = NULL;
1417 client_send_control(req, header, &reply);
1420 static void control_get_debug(TALLOC_CTX *mem_ctx,
1421 struct tevent_req *req,
1422 struct ctdb_req_header *header,
1423 struct ctdb_req_control *request)
1425 struct client_state *state = tevent_req_data(
1426 req, struct client_state);
1427 struct ctdbd_context *ctdb = state->ctdb;
1428 struct ctdb_reply_control reply;
1430 reply.rdata.opcode = request->opcode;
1431 reply.rdata.data.loglevel = (uint32_t)ctdb->log_level;
1433 reply.errmsg = NULL;
1435 client_send_control(req, header, &reply);
1438 static void control_set_debug(TALLOC_CTX *mem_ctx,
1439 struct tevent_req *req,
1440 struct ctdb_req_header *header,
1441 struct ctdb_req_control *request)
1443 struct client_state *state = tevent_req_data(
1444 req, struct client_state);
1445 struct ctdbd_context *ctdb = state->ctdb;
1446 struct ctdb_reply_control reply;
1448 ctdb->log_level = (int)request->rdata.data.loglevel;
1450 reply.rdata.opcode = request->opcode;
1452 reply.errmsg = NULL;
1454 client_send_control(req, header, &reply);
1457 static void control_get_dbmap(TALLOC_CTX *mem_ctx,
1458 struct tevent_req *req,
1459 struct ctdb_req_header *header,
1460 struct ctdb_req_control *request)
1462 struct client_state *state = tevent_req_data(
1463 req, struct client_state);
1464 struct ctdbd_context *ctdb = state->ctdb;
1465 struct ctdb_reply_control reply;
1466 struct ctdb_dbid_map *dbmap;
1469 reply.rdata.opcode = request->opcode;
1471 dbmap = talloc_zero(mem_ctx, struct ctdb_dbid_map);
1472 if (dbmap == NULL) {
1476 dbmap->num = ctdb->db_map->num_dbs;
1477 dbmap->dbs = talloc_zero_array(dbmap, struct ctdb_dbid, dbmap->num);
1478 if (dbmap->dbs == NULL) {
1482 for (i = 0; i < dbmap->num; i++) {
1483 struct database *db = &ctdb->db_map->db[i];
1484 dbmap->dbs[i] = (struct ctdb_dbid) {
1490 reply.rdata.data.dbmap = dbmap;
1492 reply.errmsg = NULL;
1493 client_send_control(req, header, &reply);
1498 reply.errmsg = "Memory error";
1499 client_send_control(req, header, &reply);
1502 static void control_get_recmode(TALLOC_CTX *mem_ctx,
1503 struct tevent_req *req,
1504 struct ctdb_req_header *header,
1505 struct ctdb_req_control *request)
1507 struct client_state *state = tevent_req_data(
1508 req, struct client_state);
1509 struct ctdbd_context *ctdb = state->ctdb;
1510 struct ctdb_reply_control reply;
1512 reply.rdata.opcode = request->opcode;
1513 reply.status = ctdb->vnn_map->recmode;
1514 reply.errmsg = NULL;
1516 client_send_control(req, header, &reply);
1519 struct set_recmode_state {
1520 struct tevent_req *req;
1521 struct ctdbd_context *ctdb;
1522 struct ctdb_req_header header;
1523 struct ctdb_reply_control reply;
1526 static void set_recmode_callback(struct tevent_req *subreq)
1528 struct set_recmode_state *substate = tevent_req_callback_data(
1529 subreq, struct set_recmode_state);
1533 status = recover_recv(subreq, &ret);
1534 TALLOC_FREE(subreq);
1536 substate->reply.status = ret;
1537 substate->reply.errmsg = "recovery failed";
1539 substate->reply.status = 0;
1540 substate->reply.errmsg = NULL;
1543 client_send_control(substate->req, &substate->header, &substate->reply);
1544 talloc_free(substate);
1547 static void control_set_recmode(TALLOC_CTX *mem_ctx,
1548 struct tevent_req *req,
1549 struct ctdb_req_header *header,
1550 struct ctdb_req_control *request)
1552 struct client_state *state = tevent_req_data(
1553 req, struct client_state);
1554 struct tevent_req *subreq;
1555 struct ctdbd_context *ctdb = state->ctdb;
1556 struct set_recmode_state *substate;
1557 struct ctdb_reply_control reply;
1559 reply.rdata.opcode = request->opcode;
1561 if (request->rdata.data.recmode == CTDB_RECOVERY_NORMAL) {
1563 reply.errmsg = "Client cannot set recmode to NORMAL";
1567 substate = talloc_zero(ctdb, struct set_recmode_state);
1568 if (substate == NULL) {
1570 reply.errmsg = "Memory error";
1574 substate->req = req;
1575 substate->ctdb = ctdb;
1576 substate->header = *header;
1577 substate->reply.rdata.opcode = request->opcode;
1579 subreq = recover_send(substate, state->ev, state->ctdb);
1580 if (subreq == NULL) {
1581 talloc_free(substate);
1584 tevent_req_set_callback(subreq, set_recmode_callback, substate);
1586 ctdb->vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
1590 client_send_control(req, header, &reply);
1594 static void srvid_handler(uint64_t srvid, TDB_DATA data, void *private_data)
1596 printf("Received a message for SRVID 0x%"PRIx64"\n", srvid);
1599 static void control_register_srvid(TALLOC_CTX *mem_ctx,
1600 struct tevent_req *req,
1601 struct ctdb_req_header *header,
1602 struct ctdb_req_control *request)
1604 struct client_state *state = tevent_req_data(
1605 req, struct client_state);
1606 struct ctdbd_context *ctdb = state->ctdb;
1607 struct ctdb_reply_control reply;
1610 reply.rdata.opcode = request->opcode;
1612 ret = srvid_register(ctdb->srv, state, request->srvid,
1613 srvid_handler, state);
1616 reply.errmsg = "Memory error";
1620 DEBUG(DEBUG_INFO, ("Register srvid 0x%"PRIx64"\n", request->srvid));
1623 reply.errmsg = NULL;
1626 client_send_control(req, header, &reply);
1629 static void control_deregister_srvid(TALLOC_CTX *mem_ctx,
1630 struct tevent_req *req,
1631 struct ctdb_req_header *header,
1632 struct ctdb_req_control *request)
1634 struct client_state *state = tevent_req_data(
1635 req, struct client_state);
1636 struct ctdbd_context *ctdb = state->ctdb;
1637 struct ctdb_reply_control reply;
1640 reply.rdata.opcode = request->opcode;
1642 ret = srvid_deregister(ctdb->srv, request->srvid, state);
1645 reply.errmsg = "srvid not registered";
1649 DEBUG(DEBUG_INFO, ("Deregister srvid 0x%"PRIx64"\n", request->srvid));
1652 reply.errmsg = NULL;
1655 client_send_control(req, header, &reply);
1658 static void control_get_dbname(TALLOC_CTX *mem_ctx,
1659 struct tevent_req *req,
1660 struct ctdb_req_header *header,
1661 struct ctdb_req_control *request)
1663 struct client_state *state = tevent_req_data(
1664 req, struct client_state);
1665 struct ctdbd_context *ctdb = state->ctdb;
1666 struct ctdb_reply_control reply;
1667 struct database *db;
1669 reply.rdata.opcode = request->opcode;
1671 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1673 reply.status = ENOENT;
1674 reply.errmsg = "Database not found";
1676 reply.rdata.data.db_name = talloc_strdup(mem_ctx, db->name);
1677 if (reply.rdata.data.db_name == NULL) {
1678 reply.status = ENOMEM;
1679 reply.errmsg = "Memory error";
1682 reply.errmsg = NULL;
1686 client_send_control(req, header, &reply);
1689 static void control_get_pid(TALLOC_CTX *mem_ctx,
1690 struct tevent_req *req,
1691 struct ctdb_req_header *header,
1692 struct ctdb_req_control *request)
1694 struct ctdb_reply_control reply;
1696 reply.rdata.opcode = request->opcode;
1697 reply.status = getpid();
1698 reply.errmsg = NULL;
1700 client_send_control(req, header, &reply);
1703 static void control_get_recmaster(TALLOC_CTX *mem_ctx,
1704 struct tevent_req *req,
1705 struct ctdb_req_header *header,
1706 struct ctdb_req_control *request)
1708 struct client_state *state = tevent_req_data(
1709 req, struct client_state);
1710 struct ctdbd_context *ctdb = state->ctdb;
1711 struct ctdb_reply_control reply;
1713 reply.rdata.opcode = request->opcode;
1714 reply.status = ctdb->node_map->recmaster;
1715 reply.errmsg = NULL;
1717 client_send_control(req, header, &reply);
1720 static void control_get_pnn(TALLOC_CTX *mem_ctx,
1721 struct tevent_req *req,
1722 struct ctdb_req_header *header,
1723 struct ctdb_req_control *request)
1725 struct ctdb_reply_control reply;
1727 reply.rdata.opcode = request->opcode;
1728 reply.status = header->destnode;
1729 reply.errmsg = NULL;
1731 client_send_control(req, header, &reply);
1734 static void control_shutdown(TALLOC_CTX *mem_ctx,
1735 struct tevent_req *req,
1736 struct ctdb_req_header *hdr,
1737 struct ctdb_req_control *request)
1739 struct client_state *state = tevent_req_data(
1740 req, struct client_state);
1745 static void control_set_tunable(TALLOC_CTX *mem_ctx,
1746 struct tevent_req *req,
1747 struct ctdb_req_header *header,
1748 struct ctdb_req_control *request)
1750 struct client_state *state = tevent_req_data(
1751 req, struct client_state);
1752 struct ctdbd_context *ctdb = state->ctdb;
1753 struct ctdb_reply_control reply;
1756 reply.rdata.opcode = request->opcode;
1757 reply.errmsg = NULL;
1759 ret = ctdb_tunable_set_value(&ctdb->tun_list,
1760 request->rdata.data.tunable->name,
1761 request->rdata.data.tunable->value,
1765 } else if (obsolete) {
1771 client_send_control(req, header, &reply);
1774 static void control_get_tunable(TALLOC_CTX *mem_ctx,
1775 struct tevent_req *req,
1776 struct ctdb_req_header *header,
1777 struct ctdb_req_control *request)
1779 struct client_state *state = tevent_req_data(
1780 req, struct client_state);
1781 struct ctdbd_context *ctdb = state->ctdb;
1782 struct ctdb_reply_control reply;
1786 reply.rdata.opcode = request->opcode;
1787 reply.errmsg = NULL;
1789 ret = ctdb_tunable_get_value(&ctdb->tun_list,
1790 request->rdata.data.tun_var, &value);
1794 reply.rdata.data.tun_value = value;
1798 client_send_control(req, header, &reply);
1801 static void control_list_tunables(TALLOC_CTX *mem_ctx,
1802 struct tevent_req *req,
1803 struct ctdb_req_header *header,
1804 struct ctdb_req_control *request)
1806 struct ctdb_reply_control reply;
1807 struct ctdb_var_list *var_list;
1809 reply.rdata.opcode = request->opcode;
1810 reply.errmsg = NULL;
1812 var_list = ctdb_tunable_names(mem_ctx);
1813 if (var_list == NULL) {
1816 reply.rdata.data.tun_var_list = var_list;
1820 client_send_control(req, header, &reply);
1823 static void control_modify_flags(TALLOC_CTX *mem_ctx,
1824 struct tevent_req *req,
1825 struct ctdb_req_header *header,
1826 struct ctdb_req_control *request)
1828 struct client_state *state = tevent_req_data(
1829 req, struct client_state);
1830 struct ctdbd_context *ctdb = state->ctdb;
1831 struct ctdb_node_flag_change *change = request->rdata.data.flag_change;
1832 struct ctdb_reply_control reply;
1835 reply.rdata.opcode = request->opcode;
1837 if ((change->old_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) ||
1838 (change->new_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
1840 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
1841 reply.status = EINVAL;
1842 reply.errmsg = "Failed to MODIFY_FLAGS";
1843 client_send_control(req, header, &reply);
1847 /* There's all sorts of broadcast weirdness here. Only change
1848 * the specified node, not the destination node of the
1850 node = &ctdb->node_map->node[change->pnn];
1853 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0 &&
1854 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
1855 DEBUG(DEBUG_INFO,("Disabling node %d\n", header->destnode));
1856 node->flags |= NODE_FLAGS_PERMANENTLY_DISABLED;
1861 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0 &&
1862 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0) {
1863 DEBUG(DEBUG_INFO,("Enabling node %d\n", header->destnode));
1864 node->flags &= ~NODE_FLAGS_PERMANENTLY_DISABLED;
1868 DEBUG(DEBUG_INFO, ("Flags unchanged for node %d\n", header->destnode));
1872 reply.errmsg = NULL;
1873 client_send_control(req, header, &reply);
1876 static void control_get_all_tunables(TALLOC_CTX *mem_ctx,
1877 struct tevent_req *req,
1878 struct ctdb_req_header *header,
1879 struct ctdb_req_control *request)
1881 struct client_state *state = tevent_req_data(
1882 req, struct client_state);
1883 struct ctdbd_context *ctdb = state->ctdb;
1884 struct ctdb_reply_control reply;
1886 reply.rdata.opcode = request->opcode;
1887 reply.rdata.data.tun_list = &ctdb->tun_list;
1889 reply.errmsg = NULL;
1891 client_send_control(req, header, &reply);
1894 static void control_uptime(TALLOC_CTX *mem_ctx,
1895 struct tevent_req *req,
1896 struct ctdb_req_header *header,
1897 struct ctdb_req_control *request)
1899 struct client_state *state = tevent_req_data(
1900 req, struct client_state);
1901 struct ctdbd_context *ctdb = state->ctdb;
1902 struct ctdb_reply_control reply;
1903 struct ctdb_uptime *uptime;;
1905 reply.rdata.opcode = request->opcode;
1907 uptime = talloc_zero(mem_ctx, struct ctdb_uptime);
1908 if (uptime == NULL) {
1912 uptime->current_time = tevent_timeval_current();
1913 uptime->ctdbd_start_time = ctdb->start_time;
1914 uptime->last_recovery_started = ctdb->recovery_start_time;
1915 uptime->last_recovery_finished = ctdb->recovery_end_time;
1917 reply.rdata.data.uptime = uptime;
1919 reply.errmsg = NULL;
1920 client_send_control(req, header, &reply);
1925 reply.errmsg = "Memory error";
1926 client_send_control(req, header, &reply);
1929 static void control_reload_nodes_file(TALLOC_CTX *mem_ctx,
1930 struct tevent_req *req,
1931 struct ctdb_req_header *header,
1932 struct ctdb_req_control *request)
1934 struct client_state *state = tevent_req_data(
1935 req, struct client_state);
1936 struct ctdbd_context *ctdb = state->ctdb;
1937 struct ctdb_reply_control reply;
1938 struct ctdb_node_map *nodemap;
1939 struct node_map *node_map = ctdb->node_map;
1942 reply.rdata.opcode = request->opcode;
1944 nodemap = read_nodes_file(mem_ctx, header->destnode);
1945 if (nodemap == NULL) {
1949 for (i=0; i<nodemap->num; i++) {
1952 if (i < node_map->num_nodes &&
1953 ctdb_sock_addr_same(&nodemap->node[i].addr,
1954 &node_map->node[i].addr)) {
1958 if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
1959 node = &node_map->node[i];
1961 node->flags |= NODE_FLAGS_DELETED;
1962 parse_ip("0.0.0.0", NULL, 0, &node->addr);
1967 if (i < node_map->num_nodes &&
1968 node_map->node[i].flags & NODE_FLAGS_DELETED) {
1969 node = &node_map->node[i];
1971 node->flags &= ~NODE_FLAGS_DELETED;
1972 node->addr = nodemap->node[i].addr;
1977 node_map->node = talloc_realloc(node_map, node_map->node,
1979 node_map->num_nodes+1);
1980 if (node_map->node == NULL) {
1983 node = &node_map->node[node_map->num_nodes];
1985 node->addr = nodemap->node[i].addr;
1986 node->pnn = nodemap->node[i].pnn;
1988 node->capabilities = CTDB_CAP_DEFAULT;
1989 node->recovery_disabled = false;
1990 node->recovery_substate = NULL;
1992 node_map->num_nodes += 1;
1995 talloc_free(nodemap);
1998 reply.errmsg = NULL;
1999 client_send_control(req, header, &reply);
2004 reply.errmsg = "Memory error";
2005 client_send_control(req, header, &reply);
2008 static void control_get_capabilities(TALLOC_CTX *mem_ctx,
2009 struct tevent_req *req,
2010 struct ctdb_req_header *header,
2011 struct ctdb_req_control *request)
2013 struct client_state *state = tevent_req_data(
2014 req, struct client_state);
2015 struct ctdbd_context *ctdb = state->ctdb;
2016 struct ctdb_reply_control reply;
2020 reply.rdata.opcode = request->opcode;
2022 node = &ctdb->node_map->node[header->destnode];
2023 caps = node->capabilities;
2025 if (node->flags & NODE_FLAGS_FAKE_TIMEOUT) {
2026 /* Don't send reply */
2030 reply.rdata.data.caps = caps;
2032 reply.errmsg = NULL;
2034 client_send_control(req, header, &reply);
2037 static void control_release_ip(TALLOC_CTX *mem_ctx,
2038 struct tevent_req *req,
2039 struct ctdb_req_header *header,
2040 struct ctdb_req_control *request)
2042 struct client_state *state = tevent_req_data(
2043 req, struct client_state);
2044 struct ctdbd_context *ctdb = state->ctdb;
2045 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2046 struct ctdb_reply_control reply;
2047 struct ctdb_public_ip_list *ips = NULL;
2048 struct ctdb_public_ip *t = NULL;
2051 reply.rdata.opcode = request->opcode;
2053 if (ctdb->known_ips == NULL) {
2054 D_INFO("RELEASE_IP %s - not a public IP\n",
2055 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2059 ips = &ctdb->known_ips[header->destnode];
2062 for (i = 0; i < ips->num; i++) {
2063 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2069 D_INFO("RELEASE_IP %s - not a public IP\n",
2070 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2074 if (t->pnn != header->destnode) {
2075 if (header->destnode == ip->pnn) {
2076 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2077 ctdb_sock_addr_to_string(mem_ctx,
2081 reply.errmsg = "RELEASE_IP to TAKE_IP node";
2082 client_send_control(req, header, &reply);
2086 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2087 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2091 D_NOTICE("RELEASE_IP %s - to node %d\n",
2092 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2099 reply.errmsg = NULL;
2100 client_send_control(req, header, &reply);
2103 static void control_takeover_ip(TALLOC_CTX *mem_ctx,
2104 struct tevent_req *req,
2105 struct ctdb_req_header *header,
2106 struct ctdb_req_control *request)
2108 struct client_state *state = tevent_req_data(
2109 req, struct client_state);
2110 struct ctdbd_context *ctdb = state->ctdb;
2111 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2112 struct ctdb_reply_control reply;
2113 struct ctdb_public_ip_list *ips = NULL;
2114 struct ctdb_public_ip *t = NULL;
2117 reply.rdata.opcode = request->opcode;
2119 if (ctdb->known_ips == NULL) {
2120 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2121 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2125 ips = &ctdb->known_ips[header->destnode];
2128 for (i = 0; i < ips->num; i++) {
2129 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2135 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2136 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2140 if (t->pnn == header->destnode) {
2141 D_INFO("TAKEOVER_IP %s - redundant\n",
2142 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2144 D_NOTICE("TAKEOVER_IP %s\n",
2145 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2151 reply.errmsg = NULL;
2152 client_send_control(req, header, &reply);
2155 static void control_get_public_ips(TALLOC_CTX *mem_ctx,
2156 struct tevent_req *req,
2157 struct ctdb_req_header *header,
2158 struct ctdb_req_control *request)
2160 struct client_state *state = tevent_req_data(
2161 req, struct client_state);
2162 struct ctdbd_context *ctdb = state->ctdb;
2163 struct ctdb_reply_control reply;
2164 struct ctdb_public_ip_list *ips = NULL;
2166 reply.rdata.opcode = request->opcode;
2168 if (ctdb->known_ips == NULL) {
2169 /* No IPs defined so create a dummy empty struct and ship it */
2170 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2172 reply.status = ENOMEM;
2173 reply.errmsg = "Memory error";
2179 ips = &ctdb->known_ips[header->destnode];
2181 if (request->flags & CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE) {
2182 /* If runstate is not RUNNING or a node is then return
2183 * no available IPs. Don't worry about interface
2184 * states here - we're not faking down to that level.
2186 if (ctdb->runstate != CTDB_RUNSTATE_RUNNING) {
2187 /* No available IPs: return dummy empty struct */
2188 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2190 reply.status = ENOMEM;
2191 reply.errmsg = "Memory error";
2198 reply.rdata.data.pubip_list = ips;
2200 reply.errmsg = NULL;
2203 client_send_control(req, header, &reply);
2206 static void control_get_nodemap(TALLOC_CTX *mem_ctx,
2207 struct tevent_req *req,
2208 struct ctdb_req_header *header,
2209 struct ctdb_req_control *request)
2211 struct client_state *state = tevent_req_data(
2212 req, struct client_state);
2213 struct ctdbd_context *ctdb = state->ctdb;
2214 struct ctdb_reply_control reply;
2215 struct ctdb_node_map *nodemap;
2219 reply.rdata.opcode = request->opcode;
2221 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
2222 if (nodemap == NULL) {
2226 nodemap->num = ctdb->node_map->num_nodes;
2227 nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2229 if (nodemap->node == NULL) {
2233 for (i=0; i<nodemap->num; i++) {
2234 node = &ctdb->node_map->node[i];
2235 nodemap->node[i] = (struct ctdb_node_and_flags) {
2237 .flags = node->flags,
2242 reply.rdata.data.nodemap = nodemap;
2244 reply.errmsg = NULL;
2245 client_send_control(req, header, &reply);
2250 reply.errmsg = "Memory error";
2251 client_send_control(req, header, &reply);
2254 static void control_get_reclock_file(TALLOC_CTX *mem_ctx,
2255 struct tevent_req *req,
2256 struct ctdb_req_header *header,
2257 struct ctdb_req_control *request)
2259 struct client_state *state = tevent_req_data(
2260 req, struct client_state);
2261 struct ctdbd_context *ctdb = state->ctdb;
2262 struct ctdb_reply_control reply;
2264 reply.rdata.opcode = request->opcode;
2266 if (ctdb->reclock != NULL) {
2267 reply.rdata.data.reclock_file =
2268 talloc_strdup(mem_ctx, ctdb->reclock);
2269 if (reply.rdata.data.reclock_file == NULL) {
2270 reply.status = ENOMEM;
2271 reply.errmsg = "Memory error";
2275 reply.rdata.data.reclock_file = NULL;
2279 reply.errmsg = NULL;
2282 client_send_control(req, header, &reply);
2285 static void control_stop_node(TALLOC_CTX *mem_ctx,
2286 struct tevent_req *req,
2287 struct ctdb_req_header *header,
2288 struct ctdb_req_control *request)
2290 struct client_state *state = tevent_req_data(
2291 req, struct client_state);
2292 struct ctdbd_context *ctdb = state->ctdb;
2293 struct ctdb_reply_control reply;
2295 reply.rdata.opcode = request->opcode;
2297 DEBUG(DEBUG_INFO, ("Stopping node\n"));
2298 ctdb->node_map->node[header->destnode].flags |= NODE_FLAGS_STOPPED;
2301 reply.errmsg = NULL;
2303 client_send_control(req, header, &reply);
2307 static void control_continue_node(TALLOC_CTX *mem_ctx,
2308 struct tevent_req *req,
2309 struct ctdb_req_header *header,
2310 struct ctdb_req_control *request)
2312 struct client_state *state = tevent_req_data(
2313 req, struct client_state);
2314 struct ctdbd_context *ctdb = state->ctdb;
2315 struct ctdb_reply_control reply;
2317 reply.rdata.opcode = request->opcode;
2319 DEBUG(DEBUG_INFO, ("Continue node\n"));
2320 ctdb->node_map->node[header->destnode].flags &= ~NODE_FLAGS_STOPPED;
2323 reply.errmsg = NULL;
2325 client_send_control(req, header, &reply);
2329 static void set_ban_state_callback(struct tevent_req *subreq)
2331 struct node *node = tevent_req_callback_data(
2332 subreq, struct node);
2335 status = tevent_wakeup_recv(subreq);
2336 TALLOC_FREE(subreq);
2338 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2341 node->flags &= ~NODE_FLAGS_BANNED;
2344 static void control_set_ban_state(TALLOC_CTX *mem_ctx,
2345 struct tevent_req *req,
2346 struct ctdb_req_header *header,
2347 struct ctdb_req_control *request)
2349 struct client_state *state = tevent_req_data(
2350 req, struct client_state);
2351 struct tevent_req *subreq;
2352 struct ctdbd_context *ctdb = state->ctdb;
2353 struct ctdb_ban_state *ban = request->rdata.data.ban_state;
2354 struct ctdb_reply_control reply;
2357 reply.rdata.opcode = request->opcode;
2359 if (ban->pnn != header->destnode) {
2361 ("SET_BAN_STATE control for PNN %d rejected\n",
2363 reply.status = EINVAL;
2367 node = &ctdb->node_map->node[header->destnode];
2369 if (ban->time == 0) {
2370 DEBUG(DEBUG_INFO,("Unbanning this node\n"));
2371 node->flags &= ~NODE_FLAGS_BANNED;
2375 subreq = tevent_wakeup_send(ctdb->node_map, state->ev,
2376 tevent_timeval_current_ofs(
2378 if (subreq == NULL) {
2379 reply.status = ENOMEM;
2382 tevent_req_set_callback(subreq, set_ban_state_callback, node);
2384 DEBUG(DEBUG_INFO, ("Banning this node for %d seconds\n", ban->time));
2385 node->flags |= NODE_FLAGS_BANNED;
2386 ctdb->vnn_map->generation = INVALID_GENERATION;
2390 reply.errmsg = NULL;
2392 client_send_control(req, header, &reply);
2396 reply.errmsg = "Failed to ban node";
2399 static void control_get_db_seqnum(TALLOC_CTX *mem_ctx,
2400 struct tevent_req *req,
2401 struct ctdb_req_header *header,
2402 struct ctdb_req_control *request)
2404 struct client_state *state = tevent_req_data(
2405 req, struct client_state);
2406 struct ctdbd_context *ctdb = state->ctdb;
2407 struct ctdb_reply_control reply;
2408 struct database *db;
2410 reply.rdata.opcode = request->opcode;
2412 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2414 reply.status = ENOENT;
2415 reply.errmsg = "Database not found";
2417 reply.rdata.data.seqnum = db->seq_num;
2419 reply.errmsg = NULL;
2422 client_send_control(req, header, &reply);
2425 static void control_db_get_health(TALLOC_CTX *mem_ctx,
2426 struct tevent_req *req,
2427 struct ctdb_req_header *header,
2428 struct ctdb_req_control *request)
2430 struct client_state *state = tevent_req_data(
2431 req, struct client_state);
2432 struct ctdbd_context *ctdb = state->ctdb;
2433 struct ctdb_reply_control reply;
2434 struct database *db;
2436 reply.rdata.opcode = request->opcode;
2438 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2440 reply.status = ENOENT;
2441 reply.errmsg = "Database not found";
2443 reply.rdata.data.reason = NULL;
2445 reply.errmsg = NULL;
2448 client_send_control(req, header, &reply);
2451 static struct ctdb_iface_list *get_ctdb_iface_list(TALLOC_CTX *mem_ctx,
2452 struct ctdbd_context *ctdb)
2454 struct ctdb_iface_list *iface_list;
2455 struct interface *iface;
2458 iface_list = talloc_zero(mem_ctx, struct ctdb_iface_list);
2459 if (iface_list == NULL) {
2463 iface_list->num = ctdb->iface_map->num;
2464 iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2466 if (iface_list->iface == NULL) {
2467 TALLOC_FREE(iface_list);
2471 for (i=0; i<iface_list->num; i++) {
2472 iface = &ctdb->iface_map->iface[i];
2473 iface_list->iface[i] = (struct ctdb_iface) {
2474 .link_state = iface->link_up,
2475 .references = iface->references,
2477 strlcpy(iface_list->iface[i].name, iface->name,
2478 sizeof(iface_list->iface[i].name));
2485 static void control_get_public_ip_info(TALLOC_CTX *mem_ctx,
2486 struct tevent_req *req,
2487 struct ctdb_req_header *header,
2488 struct ctdb_req_control *request)
2490 struct client_state *state = tevent_req_data(
2491 req, struct client_state);
2492 struct ctdbd_context *ctdb = state->ctdb;
2493 struct ctdb_reply_control reply;
2494 ctdb_sock_addr *addr = request->rdata.data.addr;
2495 struct ctdb_public_ip_list *known = NULL;
2496 struct ctdb_public_ip_info *info = NULL;
2499 reply.rdata.opcode = request->opcode;
2501 info = talloc_zero(mem_ctx, struct ctdb_public_ip_info);
2503 reply.status = ENOMEM;
2504 reply.errmsg = "Memory error";
2508 reply.rdata.data.ipinfo = info;
2510 if (ctdb->known_ips != NULL) {
2511 known = &ctdb->known_ips[header->destnode];
2513 /* No IPs defined so create a dummy empty struct and
2514 * fall through. The given IP won't be matched
2517 known = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2518 if (known == NULL) {
2519 reply.status = ENOMEM;
2520 reply.errmsg = "Memory error";
2525 for (i = 0; i < known->num; i++) {
2526 if (ctdb_sock_addr_same_ip(&known->ip[i].addr,
2532 if (i == known->num) {
2533 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
2534 ctdb_sock_addr_to_string(mem_ctx, addr, false));
2536 reply.errmsg = "Unknown address";
2540 info->ip = known->ip[i];
2542 /* The fake PUBLICIPS stanza and resulting known_ips data
2543 * don't know anything about interfaces, so completely fake
2546 info->active_idx = 0;
2548 info->ifaces = get_ctdb_iface_list(mem_ctx, ctdb);
2549 if (info->ifaces == NULL) {
2550 reply.status = ENOMEM;
2551 reply.errmsg = "Memory error";
2556 reply.errmsg = NULL;
2559 client_send_control(req, header, &reply);
2562 static void control_get_ifaces(TALLOC_CTX *mem_ctx,
2563 struct tevent_req *req,
2564 struct ctdb_req_header *header,
2565 struct ctdb_req_control *request)
2567 struct client_state *state = tevent_req_data(
2568 req, struct client_state);
2569 struct ctdbd_context *ctdb = state->ctdb;
2570 struct ctdb_reply_control reply;
2571 struct ctdb_iface_list *iface_list;
2573 reply.rdata.opcode = request->opcode;
2575 iface_list = get_ctdb_iface_list(mem_ctx, ctdb);
2576 if (iface_list == NULL) {
2580 reply.rdata.data.iface_list = iface_list;
2582 reply.errmsg = NULL;
2583 client_send_control(req, header, &reply);
2588 reply.errmsg = "Memory error";
2589 client_send_control(req, header, &reply);
2592 static void control_set_iface_link_state(TALLOC_CTX *mem_ctx,
2593 struct tevent_req *req,
2594 struct ctdb_req_header *header,
2595 struct ctdb_req_control *request)
2597 struct client_state *state = tevent_req_data(
2598 req, struct client_state);
2599 struct ctdbd_context *ctdb = state->ctdb;
2600 struct ctdb_reply_control reply;
2601 struct ctdb_iface *in_iface;
2602 struct interface *iface = NULL;
2603 bool link_up = false;
2606 reply.rdata.opcode = request->opcode;
2608 in_iface = request->rdata.data.iface;
2610 if (in_iface->name[CTDB_IFACE_SIZE] != '\0') {
2611 reply.errmsg = "interface name not terminated";
2615 switch (in_iface->link_state) {
2625 reply.errmsg = "invalid link state";
2629 if (in_iface->references != 0) {
2630 reply.errmsg = "references should be 0";
2634 for (i=0; i<ctdb->iface_map->num; i++) {
2635 if (strcmp(ctdb->iface_map->iface[i].name,
2636 in_iface->name) == 0) {
2637 iface = &ctdb->iface_map->iface[i];
2642 if (iface == NULL) {
2643 reply.errmsg = "interface not found";
2647 iface->link_up = link_up;
2650 reply.errmsg = NULL;
2651 client_send_control(req, header, &reply);
2656 client_send_control(req, header, &reply);
2659 static void control_set_db_readonly(TALLOC_CTX *mem_ctx,
2660 struct tevent_req *req,
2661 struct ctdb_req_header *header,
2662 struct ctdb_req_control *request)
2664 struct client_state *state = tevent_req_data(
2665 req, struct client_state);
2666 struct ctdbd_context *ctdb = state->ctdb;
2667 struct ctdb_reply_control reply;
2668 struct database *db;
2670 reply.rdata.opcode = request->opcode;
2672 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2674 reply.status = ENOENT;
2675 reply.errmsg = "Database not found";
2679 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
2680 reply.status = EINVAL;
2681 reply.errmsg = "Can not set READONLY on persistent db";
2685 db->flags |= CTDB_DB_FLAGS_READONLY;
2687 reply.errmsg = NULL;
2690 client_send_control(req, header, &reply);
2693 static void control_set_db_sticky(TALLOC_CTX *mem_ctx,
2694 struct tevent_req *req,
2695 struct ctdb_req_header *header,
2696 struct ctdb_req_control *request)
2698 struct client_state *state = tevent_req_data(
2699 req, struct client_state);
2700 struct ctdbd_context *ctdb = state->ctdb;
2701 struct ctdb_reply_control reply;
2702 struct database *db;
2704 reply.rdata.opcode = request->opcode;
2706 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2708 reply.status = ENOENT;
2709 reply.errmsg = "Database not found";
2713 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
2714 reply.status = EINVAL;
2715 reply.errmsg = "Can not set STICKY on persistent db";
2719 db->flags |= CTDB_DB_FLAGS_STICKY;
2721 reply.errmsg = NULL;
2724 client_send_control(req, header, &reply);
2727 static void control_ipreallocated(TALLOC_CTX *mem_ctx,
2728 struct tevent_req *req,
2729 struct ctdb_req_header *header,
2730 struct ctdb_req_control *request)
2732 struct ctdb_reply_control reply;
2734 /* Always succeed */
2735 reply.rdata.opcode = request->opcode;
2737 reply.errmsg = NULL;
2739 client_send_control(req, header, &reply);
2742 static void control_get_runstate(TALLOC_CTX *mem_ctx,
2743 struct tevent_req *req,
2744 struct ctdb_req_header *header,
2745 struct ctdb_req_control *request)
2747 struct client_state *state = tevent_req_data(
2748 req, struct client_state);
2749 struct ctdbd_context *ctdb = state->ctdb;
2750 struct ctdb_reply_control reply;
2752 reply.rdata.opcode = request->opcode;
2753 reply.rdata.data.runstate = ctdb->runstate;
2755 reply.errmsg = NULL;
2757 client_send_control(req, header, &reply);
2760 static void control_get_nodes_file(TALLOC_CTX *mem_ctx,
2761 struct tevent_req *req,
2762 struct ctdb_req_header *header,
2763 struct ctdb_req_control *request)
2765 struct ctdb_reply_control reply;
2766 struct ctdb_node_map *nodemap;
2768 reply.rdata.opcode = request->opcode;
2770 nodemap = read_nodes_file(mem_ctx, header->destnode);
2771 if (nodemap == NULL) {
2775 reply.rdata.data.nodemap = nodemap;
2777 reply.errmsg = NULL;
2778 client_send_control(req, header, &reply);
2783 reply.errmsg = "Failed to read nodes file";
2784 client_send_control(req, header, &reply);
2787 static void control_check_pid_srvid(TALLOC_CTX *mem_ctx,
2788 struct tevent_req *req,
2789 struct ctdb_req_header *header,
2790 struct ctdb_req_control *request)
2792 struct client_state *state = tevent_req_data(
2793 req, struct client_state);
2794 struct ctdbd_context *ctdb = state->ctdb;
2795 struct ctdb_client *client;
2796 struct client_state *cstate;
2797 struct ctdb_reply_control reply;
2798 bool pid_found, srvid_found;
2801 reply.rdata.opcode = request->opcode;
2804 srvid_found = false;
2806 for (client=ctdb->client_list; client != NULL; client=client->next) {
2807 if (client->pid == request->rdata.data.pid_srvid->pid) {
2809 cstate = (struct client_state *)client->state;
2810 ret = srvid_exists(ctdb->srv,
2811 request->rdata.data.pid_srvid->srvid,
2815 ret = kill(cstate->pid, 0);
2818 reply.errmsg = strerror(errno);
2821 reply.errmsg = NULL;
2829 reply.errmsg = "No client for PID";
2830 } else if (! srvid_found) {
2832 reply.errmsg = "No client for PID and SRVID";
2835 client_send_control(req, header, &reply);
2838 static bool fake_control_failure(TALLOC_CTX *mem_ctx,
2839 struct tevent_req *req,
2840 struct ctdb_req_header *header,
2841 struct ctdb_req_control *request)
2843 struct client_state *state = tevent_req_data(
2844 req, struct client_state);
2845 struct ctdbd_context *ctdb = state->ctdb;
2846 struct ctdb_reply_control reply;
2847 struct fake_control_failure *f = NULL;
2849 D_DEBUG("Checking fake control failure for control %u on node %u\n",
2850 request->opcode, header->destnode);
2851 for (f = ctdb->control_failures; f != NULL; f = f->next) {
2852 if (f->opcode == request->opcode &&
2853 (f->pnn == header->destnode ||
2854 f->pnn == CTDB_UNKNOWN_PNN)) {
2856 reply.rdata.opcode = request->opcode;
2857 if (strcmp(f->error, "TIMEOUT") == 0) {
2858 /* Causes no reply */
2859 D_ERR("Control %u fake timeout on node %u\n",
2860 request->opcode, header->destnode);
2862 } else if (strcmp(f->error, "ERROR") == 0) {
2863 D_ERR("Control %u fake error on node %u\n",
2864 request->opcode, header->destnode);
2866 reply.errmsg = f->comment;
2867 client_send_control(req, header, &reply);
2876 static void control_error(TALLOC_CTX *mem_ctx,
2877 struct tevent_req *req,
2878 struct ctdb_req_header *header,
2879 struct ctdb_req_control *request)
2881 struct ctdb_reply_control reply;
2883 reply.rdata.opcode = request->opcode;
2885 reply.errmsg = "Not implemented";
2887 client_send_control(req, header, &reply);
2891 * Handling protocol - messages
2894 struct disable_recoveries_state {
2898 static void disable_recoveries_callback(struct tevent_req *subreq)
2900 struct disable_recoveries_state *substate = tevent_req_callback_data(
2901 subreq, struct disable_recoveries_state);
2904 status = tevent_wakeup_recv(subreq);
2905 TALLOC_FREE(subreq);
2907 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2910 substate->node->recovery_disabled = false;
2911 TALLOC_FREE(substate->node->recovery_substate);
2914 static void message_disable_recoveries(TALLOC_CTX *mem_ctx,
2915 struct tevent_req *req,
2916 struct ctdb_req_header *header,
2917 struct ctdb_req_message *request)
2919 struct client_state *state = tevent_req_data(
2920 req, struct client_state);
2921 struct tevent_req *subreq;
2922 struct ctdbd_context *ctdb = state->ctdb;
2923 struct disable_recoveries_state *substate;
2924 struct ctdb_disable_message *disable = request->data.disable;
2925 struct ctdb_req_message_data reply;
2930 node = &ctdb->node_map->node[header->destnode];
2932 if (disable->timeout == 0) {
2933 TALLOC_FREE(node->recovery_substate);
2934 node->recovery_disabled = false;
2935 DEBUG(DEBUG_INFO, ("Enabled recoveries on node %u\n",
2940 substate = talloc_zero(ctdb->node_map,
2941 struct disable_recoveries_state);
2942 if (substate == NULL) {
2946 substate->node = node;
2948 subreq = tevent_wakeup_send(substate, state->ev,
2949 tevent_timeval_current_ofs(
2950 disable->timeout, 0));
2951 if (subreq == NULL) {
2952 talloc_free(substate);
2955 tevent_req_set_callback(subreq, disable_recoveries_callback, substate);
2957 DEBUG(DEBUG_INFO, ("Disabled recoveries for %d seconds on node %u\n",
2958 disable->timeout, header->destnode));
2959 node->recovery_substate = substate;
2960 node->recovery_disabled = true;
2963 ret = header->destnode;
2966 reply.srvid = disable->srvid;
2967 data.dptr = (uint8_t *)&ret;
2968 data.dsize = sizeof(int);
2971 client_send_message(req, header, &reply);
2974 static void message_takeover_run(TALLOC_CTX *mem_ctx,
2975 struct tevent_req *req,
2976 struct ctdb_req_header *header,
2977 struct ctdb_req_message *request)
2979 struct client_state *state = tevent_req_data(
2980 req, struct client_state);
2981 struct ctdbd_context *ctdb = state->ctdb;
2982 struct ctdb_srvid_message *srvid = request->data.msg;
2983 struct ctdb_req_message_data reply;
2987 if (header->destnode != ctdb->node_map->recmaster) {
2988 /* No reply! Only recmaster replies... */
2992 DEBUG(DEBUG_INFO, ("IP takover run on node %u\n",
2994 ret = header->destnode;
2996 reply.srvid = srvid->srvid;
2997 data.dptr = (uint8_t *)&ret;
2998 data.dsize = sizeof(int);
3001 client_send_message(req, header, &reply);
3005 * Handle a single client
3008 static void client_read_handler(uint8_t *buf, size_t buflen,
3009 void *private_data);
3010 static void client_dead_handler(void *private_data);
3011 static void client_process_packet(struct tevent_req *req,
3012 uint8_t *buf, size_t buflen);
3013 static void client_process_message(struct tevent_req *req,
3014 uint8_t *buf, size_t buflen);
3015 static void client_process_control(struct tevent_req *req,
3016 uint8_t *buf, size_t buflen);
3017 static void client_reply_done(struct tevent_req *subreq);
3019 static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
3020 struct tevent_context *ev,
3021 int fd, struct ctdbd_context *ctdb,
3024 struct tevent_req *req;
3025 struct client_state *state;
3027 socklen_t crl = sizeof(struct ucred);
3030 req = tevent_req_create(mem_ctx, &state, struct client_state);
3040 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
3042 tevent_req_error(req, ret);
3043 return tevent_req_post(req, ev);
3045 state->pid = cr.pid;
3047 ret = comm_setup(state, ev, fd, client_read_handler, req,
3048 client_dead_handler, req, &state->comm);
3050 tevent_req_error(req, ret);
3051 return tevent_req_post(req, ev);
3054 ret = client_add(ctdb, state->pid, state);
3056 tevent_req_error(req, ret);
3057 return tevent_req_post(req, ev);
3060 DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
3065 static void client_read_handler(uint8_t *buf, size_t buflen,
3068 struct tevent_req *req = talloc_get_type_abort(
3069 private_data, struct tevent_req);
3070 struct client_state *state = tevent_req_data(
3071 req, struct client_state);
3072 struct ctdbd_context *ctdb = state->ctdb;
3073 struct ctdb_req_header header;
3077 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3082 if (buflen != header.length) {
3086 ret = ctdb_req_header_verify(&header, 0);
3091 header_fix_pnn(&header, ctdb);
3093 if (header.destnode == CTDB_BROADCAST_ALL) {
3094 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3095 header.destnode = i;
3097 ctdb_req_header_push(&header, buf, &np);
3098 client_process_packet(req, buf, buflen);
3103 if (header.destnode == CTDB_BROADCAST_CONNECTED) {
3104 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3105 if (ctdb->node_map->node[i].flags &
3106 NODE_FLAGS_DISCONNECTED) {
3110 header.destnode = i;
3112 ctdb_req_header_push(&header, buf, &np);
3113 client_process_packet(req, buf, buflen);
3118 if (header.destnode > ctdb->node_map->num_nodes) {
3119 fprintf(stderr, "Invalid destination pnn 0x%x\n",
3125 if (ctdb->node_map->node[header.destnode].flags & NODE_FLAGS_DISCONNECTED) {
3126 fprintf(stderr, "Packet for disconnected node pnn %u\n",
3131 ctdb_req_header_push(&header, buf, &np);
3132 client_process_packet(req, buf, buflen);
3135 static void client_dead_handler(void *private_data)
3137 struct tevent_req *req = talloc_get_type_abort(
3138 private_data, struct tevent_req);
3140 tevent_req_done(req);
3143 static void client_process_packet(struct tevent_req *req,
3144 uint8_t *buf, size_t buflen)
3146 struct ctdb_req_header header;
3150 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3155 switch (header.operation) {
3156 case CTDB_REQ_MESSAGE:
3157 client_process_message(req, buf, buflen);
3160 case CTDB_REQ_CONTROL:
3161 client_process_control(req, buf, buflen);
3169 static void client_process_message(struct tevent_req *req,
3170 uint8_t *buf, size_t buflen)
3172 struct client_state *state = tevent_req_data(
3173 req, struct client_state);
3174 struct ctdbd_context *ctdb = state->ctdb;
3175 TALLOC_CTX *mem_ctx;
3176 struct ctdb_req_header header;
3177 struct ctdb_req_message request;
3181 mem_ctx = talloc_new(state);
3182 if (tevent_req_nomem(mem_ctx, req)) {
3186 ret = ctdb_req_message_pull(buf, buflen, &header, mem_ctx, &request);
3188 talloc_free(mem_ctx);
3189 tevent_req_error(req, ret);
3193 header_fix_pnn(&header, ctdb);
3195 if (header.destnode >= ctdb->node_map->num_nodes) {
3196 /* Many messages are not replied to, so just behave as
3197 * though this message was not received */
3198 fprintf(stderr, "Invalid node %d\n", header.destnode);
3199 talloc_free(mem_ctx);
3203 srvid = request.srvid;
3204 DEBUG(DEBUG_INFO, ("request srvid = 0x%"PRIx64"\n", srvid));
3206 if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
3207 message_disable_recoveries(mem_ctx, req, &header, &request);
3208 } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
3209 message_takeover_run(mem_ctx, req, &header, &request);
3213 talloc_free(mem_ctx);
3216 static void client_process_control(struct tevent_req *req,
3217 uint8_t *buf, size_t buflen)
3219 struct client_state *state = tevent_req_data(
3220 req, struct client_state);
3221 struct ctdbd_context *ctdb = state->ctdb;
3222 TALLOC_CTX *mem_ctx;
3223 struct ctdb_req_header header;
3224 struct ctdb_req_control request;
3227 mem_ctx = talloc_new(state);
3228 if (tevent_req_nomem(mem_ctx, req)) {
3232 ret = ctdb_req_control_pull(buf, buflen, &header, mem_ctx, &request);
3234 talloc_free(mem_ctx);
3235 tevent_req_error(req, ret);
3239 header_fix_pnn(&header, ctdb);
3241 if (header.destnode >= ctdb->node_map->num_nodes) {
3242 struct ctdb_reply_control reply;
3244 reply.rdata.opcode = request.opcode;
3245 reply.errmsg = "Invalid node";
3247 client_send_control(req, &header, &reply);
3251 DEBUG(DEBUG_INFO, ("request opcode = %u, reqid = %u\n",
3252 request.opcode, header.reqid));
3254 if (fake_control_failure(mem_ctx, req, &header, &request)) {
3258 switch (request.opcode) {
3259 case CTDB_CONTROL_PROCESS_EXISTS:
3260 control_process_exists(mem_ctx, req, &header, &request);
3263 case CTDB_CONTROL_PING:
3264 control_ping(mem_ctx, req, &header, &request);
3267 case CTDB_CONTROL_GETDBPATH:
3268 control_getdbpath(mem_ctx, req, &header, &request);
3271 case CTDB_CONTROL_GETVNNMAP:
3272 control_getvnnmap(mem_ctx, req, &header, &request);
3275 case CTDB_CONTROL_GET_DEBUG:
3276 control_get_debug(mem_ctx, req, &header, &request);
3279 case CTDB_CONTROL_SET_DEBUG:
3280 control_set_debug(mem_ctx, req, &header, &request);
3283 case CTDB_CONTROL_GET_DBMAP:
3284 control_get_dbmap(mem_ctx, req, &header, &request);
3287 case CTDB_CONTROL_GET_RECMODE:
3288 control_get_recmode(mem_ctx, req, &header, &request);
3291 case CTDB_CONTROL_SET_RECMODE:
3292 control_set_recmode(mem_ctx, req, &header, &request);
3295 case CTDB_CONTROL_REGISTER_SRVID:
3296 control_register_srvid(mem_ctx, req, &header, &request);
3299 case CTDB_CONTROL_DEREGISTER_SRVID:
3300 control_deregister_srvid(mem_ctx, req, &header, &request);
3303 case CTDB_CONTROL_GET_DBNAME:
3304 control_get_dbname(mem_ctx, req, &header, &request);
3307 case CTDB_CONTROL_GET_PID:
3308 control_get_pid(mem_ctx, req, &header, &request);
3311 case CTDB_CONTROL_GET_RECMASTER:
3312 control_get_recmaster(mem_ctx, req, &header, &request);
3315 case CTDB_CONTROL_GET_PNN:
3316 control_get_pnn(mem_ctx, req, &header, &request);
3319 case CTDB_CONTROL_SHUTDOWN:
3320 control_shutdown(mem_ctx, req, &header, &request);
3323 case CTDB_CONTROL_SET_TUNABLE:
3324 control_set_tunable(mem_ctx, req, &header, &request);
3327 case CTDB_CONTROL_GET_TUNABLE:
3328 control_get_tunable(mem_ctx, req, &header, &request);
3331 case CTDB_CONTROL_LIST_TUNABLES:
3332 control_list_tunables(mem_ctx, req, &header, &request);
3335 case CTDB_CONTROL_MODIFY_FLAGS:
3336 control_modify_flags(mem_ctx, req, &header, &request);
3339 case CTDB_CONTROL_GET_ALL_TUNABLES:
3340 control_get_all_tunables(mem_ctx, req, &header, &request);
3343 case CTDB_CONTROL_UPTIME:
3344 control_uptime(mem_ctx, req, &header, &request);
3347 case CTDB_CONTROL_RELOAD_NODES_FILE:
3348 control_reload_nodes_file(mem_ctx, req, &header, &request);
3351 case CTDB_CONTROL_GET_CAPABILITIES:
3352 control_get_capabilities(mem_ctx, req, &header, &request);
3355 case CTDB_CONTROL_RELEASE_IP:
3356 control_release_ip(mem_ctx, req, &header, &request);
3359 case CTDB_CONTROL_TAKEOVER_IP:
3360 control_takeover_ip(mem_ctx, req, &header, &request);
3363 case CTDB_CONTROL_GET_PUBLIC_IPS:
3364 control_get_public_ips(mem_ctx, req, &header, &request);
3367 case CTDB_CONTROL_GET_NODEMAP:
3368 control_get_nodemap(mem_ctx, req, &header, &request);
3371 case CTDB_CONTROL_GET_RECLOCK_FILE:
3372 control_get_reclock_file(mem_ctx, req, &header, &request);
3375 case CTDB_CONTROL_STOP_NODE:
3376 control_stop_node(mem_ctx, req, &header, &request);
3379 case CTDB_CONTROL_CONTINUE_NODE:
3380 control_continue_node(mem_ctx, req, &header, &request);
3383 case CTDB_CONTROL_SET_BAN_STATE:
3384 control_set_ban_state(mem_ctx, req, &header, &request);
3387 case CTDB_CONTROL_GET_DB_SEQNUM:
3388 control_get_db_seqnum(mem_ctx, req, &header, &request);
3391 case CTDB_CONTROL_DB_GET_HEALTH:
3392 control_db_get_health(mem_ctx, req, &header, &request);
3395 case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
3396 control_get_public_ip_info(mem_ctx, req, &header, &request);
3399 case CTDB_CONTROL_GET_IFACES:
3400 control_get_ifaces(mem_ctx, req, &header, &request);
3403 case CTDB_CONTROL_SET_IFACE_LINK_STATE:
3404 control_set_iface_link_state(mem_ctx, req, &header, &request);
3407 case CTDB_CONTROL_SET_DB_READONLY:
3408 control_set_db_readonly(mem_ctx, req, &header, &request);
3411 case CTDB_CONTROL_SET_DB_STICKY:
3412 control_set_db_sticky(mem_ctx, req, &header, &request);
3415 case CTDB_CONTROL_IPREALLOCATED:
3416 control_ipreallocated(mem_ctx, req, &header, &request);
3419 case CTDB_CONTROL_GET_RUNSTATE:
3420 control_get_runstate(mem_ctx, req, &header, &request);
3423 case CTDB_CONTROL_GET_NODES_FILE:
3424 control_get_nodes_file(mem_ctx, req, &header, &request);
3427 case CTDB_CONTROL_CHECK_PID_SRVID:
3428 control_check_pid_srvid(mem_ctx, req, &header, &request);
3432 if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) {
3433 control_error(mem_ctx, req, &header, &request);
3439 talloc_free(mem_ctx);
3442 static int client_recv(struct tevent_req *req, int *perr)
3444 struct client_state *state = tevent_req_data(
3445 req, struct client_state);
3448 DEBUG(DEBUG_INFO, ("Client done fd=%d\n", state->fd));
3451 if (tevent_req_is_unix_error(req, &err)) {
3458 return state->status;
3465 struct server_state {
3466 struct tevent_context *ev;
3467 struct ctdbd_context *ctdb;
3471 static void server_new_client(struct tevent_req *subreq);
3472 static void server_client_done(struct tevent_req *subreq);
3474 static struct tevent_req *server_send(TALLOC_CTX *mem_ctx,
3475 struct tevent_context *ev,
3476 struct ctdbd_context *ctdb,
3479 struct tevent_req *req, *subreq;
3480 struct server_state *state;
3482 req = tevent_req_create(mem_ctx, &state, struct server_state);
3491 subreq = accept_send(state, ev, fd);
3492 if (tevent_req_nomem(subreq, req)) {
3493 return tevent_req_post(req, ev);
3495 tevent_req_set_callback(subreq, server_new_client, req);
3500 static void server_new_client(struct tevent_req *subreq)
3502 struct tevent_req *req = tevent_req_callback_data(
3503 subreq, struct tevent_req);
3504 struct server_state *state = tevent_req_data(
3505 req, struct server_state);
3506 struct ctdbd_context *ctdb = state->ctdb;
3510 client_fd = accept_recv(subreq, NULL, NULL, &ret);
3511 TALLOC_FREE(subreq);
3512 if (client_fd == -1) {
3513 tevent_req_error(req, ret);
3517 subreq = client_send(state, state->ev, client_fd,
3518 ctdb, ctdb->node_map->pnn);
3519 if (tevent_req_nomem(subreq, req)) {
3522 tevent_req_set_callback(subreq, server_client_done, req);
3524 ctdb->num_clients += 1;
3526 subreq = accept_send(state, state->ev, state->fd);
3527 if (tevent_req_nomem(subreq, req)) {
3530 tevent_req_set_callback(subreq, server_new_client, req);
3533 static void server_client_done(struct tevent_req *subreq)
3535 struct tevent_req *req = tevent_req_callback_data(
3536 subreq, struct tevent_req);
3537 struct server_state *state = tevent_req_data(
3538 req, struct server_state);
3539 struct ctdbd_context *ctdb = state->ctdb;
3543 status = client_recv(subreq, &ret);
3544 TALLOC_FREE(subreq);
3546 tevent_req_error(req, ret);
3550 ctdb->num_clients -= 1;
3553 /* Special status, to shutdown server */
3554 DEBUG(DEBUG_INFO, ("Shutting down server\n"));
3555 tevent_req_done(req);
3559 static bool server_recv(struct tevent_req *req, int *perr)
3563 if (tevent_req_is_unix_error(req, &err)) {
3576 static int socket_init(const char *sockpath)
3578 struct sockaddr_un addr;
3582 memset(&addr, 0, sizeof(addr));
3583 addr.sun_family = AF_UNIX;
3585 len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
3586 if (len >= sizeof(addr.sun_path)) {
3587 fprintf(stderr, "path too long: %s\n", sockpath);
3591 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3593 fprintf(stderr, "socket failed - %s\n", sockpath);
3597 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
3599 fprintf(stderr, "bind failed - %s\n", sockpath);
3603 ret = listen(fd, 10);
3605 fprintf(stderr, "listen failed\n");
3609 DEBUG(DEBUG_INFO, ("Socket init done\n"));
3620 static struct options {
3621 const char *sockpath;
3622 const char *pidfile;
3623 const char *debuglevel;
3626 static struct poptOption cmdline_options[] = {
3627 { "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
3628 "Unix domain socket path", "filename" },
3629 { "pidfile", 'p', POPT_ARG_STRING, &options.pidfile, 0,
3630 "pid file", "filename" } ,
3631 { "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
3632 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
3635 static void cleanup(void)
3637 unlink(options.sockpath);
3638 unlink(options.pidfile);
3641 static void signal_handler(int sig)
3647 static void start_server(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3648 struct ctdbd_context *ctdb, int fd, int pfd)
3650 struct tevent_req *req;
3655 signal(SIGTERM, signal_handler);
3657 req = server_send(mem_ctx, ev, ctdb, fd);
3659 fprintf(stderr, "Memory error\n");
3663 len = write(pfd, &ret, sizeof(ret));
3664 if (len != sizeof(ret)) {
3665 fprintf(stderr, "Failed to send message to parent\n");
3670 tevent_req_poll(req, ev);
3672 server_recv(req, &ret);
3678 int main(int argc, const char *argv[])
3680 TALLOC_CTX *mem_ctx;
3681 struct ctdbd_context *ctdb;
3682 struct tevent_context *ev;
3684 int opt, fd, ret, pfd[2];
3689 pc = poptGetContext(argv[0], argc, argv, cmdline_options,
3690 POPT_CONTEXT_KEEP_FIRST);
3691 while ((opt = poptGetNextOpt(pc)) != -1) {
3692 fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
3696 if (options.sockpath == NULL) {
3697 fprintf(stderr, "Please specify socket path\n");
3698 poptPrintHelp(pc, stdout, 0);
3702 if (options.pidfile == NULL) {
3703 fprintf(stderr, "Please specify pid file\n");
3704 poptPrintHelp(pc, stdout, 0);
3708 mem_ctx = talloc_new(NULL);
3709 if (mem_ctx == NULL) {
3710 fprintf(stderr, "Memory error\n");
3714 ret = logging_init(mem_ctx, "file:", options.debuglevel, "fake-ctdbd");
3716 fprintf(stderr, "Invalid debug level\n");
3717 poptPrintHelp(pc, stdout, 0);
3721 ctdb = ctdbd_setup(mem_ctx);
3726 if (! ctdbd_verify(ctdb)) {
3730 ev = tevent_context_init(mem_ctx);
3732 fprintf(stderr, "Memory error\n");
3736 fd = socket_init(options.sockpath);
3743 fprintf(stderr, "Failed to create pipe\n");
3750 fprintf(stderr, "Failed to fork\n");
3758 start_server(mem_ctx, ev, ctdb, fd, pfd[1]);
3765 len = read(pfd[0], &ret, sizeof(ret));
3767 if (len != sizeof(ret)) {
3768 fprintf(stderr, "len = %zi\n", len);
3769 fprintf(stderr, "Failed to get message from child\n");
3774 fp = fopen(options.pidfile, "w");
3776 fprintf(stderr, "Failed to open pid file %s\n",
3781 fprintf(fp, "%d\n", pid);