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"
23 #include "system/filesys.h"
30 #include "lib/util/dlinklist.h"
31 #include "lib/util/tevent_unix.h"
32 #include "lib/util/debug.h"
33 #include "lib/util/samba_util.h"
34 #include "lib/util/util_file.h"
35 #include "lib/async_req/async_sock.h"
37 #include "protocol/protocol.h"
38 #include "protocol/protocol_api.h"
39 #include "protocol/protocol_util.h"
40 #include "protocol/protocol_private.h"
42 #include "common/comm.h"
43 #include "common/logging.h"
44 #include "common/tunable.h"
45 #include "common/srvid.h"
46 #include "common/system.h"
48 #include "ipalloc_read_known_ips.h"
51 #define CTDB_PORT 4379
53 /* A fake flag that is only supported by some functions */
54 #define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
60 uint32_t capabilities;
61 bool recovery_disabled;
62 void *recovery_substate;
78 struct interface_map {
80 struct interface *iface;
91 struct database *prev, *next;
94 struct tdb_context *tdb;
100 struct database_map {
105 struct fake_control_failure {
106 struct fake_control_failure *prev, *next;
107 enum ctdb_controls opcode;
114 struct ctdb_client *prev, *next;
115 struct ctdbd_context *ctdb;
120 struct ctdbd_context {
121 struct node_map *node_map;
122 struct interface_map *iface_map;
123 struct vnn_map *vnn_map;
124 struct database_map *db_map;
125 struct srvid_context *srv;
127 struct timeval start_time;
128 struct timeval recovery_start_time;
129 struct timeval recovery_end_time;
130 bool takeover_disabled;
132 enum ctdb_runstate runstate;
133 struct ctdb_tunable_list tun_list;
135 struct ctdb_public_ip_list *known_ips;
136 struct fake_control_failure *control_failures;
137 struct ctdb_client *client_list;
144 static struct node_map *nodemap_init(TALLOC_CTX *mem_ctx)
146 struct node_map *node_map;
148 node_map = talloc_zero(mem_ctx, struct node_map);
149 if (node_map == NULL) {
153 node_map->pnn = CTDB_UNKNOWN_PNN;
154 node_map->recmaster = CTDB_UNKNOWN_PNN;
159 /* Read a nodemap from stdin. Each line looks like:
160 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
161 * EOF or a blank line terminates input.
163 * By default, capabilities for each node are
164 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER. These 2
165 * capabilities can be faked off by adding, for example,
166 * -CTDB_CAP_RECMASTER.
169 static bool nodemap_parse(struct node_map *node_map)
173 while ((fgets(line, sizeof(line), stdin) != NULL)) {
174 uint32_t pnn, flags, capabilities;
177 ctdb_sock_addr saddr;
181 if (line[0] == '\n') {
185 /* Get rid of pesky newline */
186 if ((t = strchr(line, '\n')) != NULL) {
191 tok = strtok(line, " \t");
193 fprintf(stderr, "bad line (%s) - missing PNN\n", line);
196 pnn = (uint32_t)strtoul(tok, NULL, 0);
199 tok = strtok(NULL, " \t");
201 fprintf(stderr, "bad line (%s) - missing IP\n", line);
204 ret = ctdb_sock_addr_from_string(tok, &saddr, false);
206 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
209 ctdb_sock_addr_set_port(&saddr, CTDB_PORT);
210 ip = talloc_strdup(node_map, tok);
216 tok = strtok(NULL, " \t");
218 fprintf(stderr, "bad line (%s) - missing flags\n",
222 flags = (uint32_t)strtoul(tok, NULL, 0);
223 /* Handle deleted nodes */
224 if (flags & NODE_FLAGS_DELETED) {
226 ip = talloc_strdup(node_map, "0.0.0.0");
231 capabilities = CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER;
233 tok = strtok(NULL, " \t");
234 while (tok != NULL) {
235 if (strcmp(tok, "CURRENT") == 0) {
237 } else if (strcmp(tok, "RECMASTER") == 0) {
238 node_map->recmaster = pnn;
239 } else if (strcmp(tok, "-CTDB_CAP_RECMASTER") == 0) {
240 capabilities &= ~CTDB_CAP_RECMASTER;
241 } else if (strcmp(tok, "-CTDB_CAP_LMASTER") == 0) {
242 capabilities &= ~CTDB_CAP_LMASTER;
243 } else if (strcmp(tok, "TIMEOUT") == 0) {
244 /* This can be done with just a flag
245 * value but it is probably clearer
246 * and less error-prone to fake this
247 * with an explicit token */
248 flags |= NODE_FLAGS_FAKE_TIMEOUT;
250 tok = strtok(NULL, " \t");
253 node_map->node = talloc_realloc(node_map, node_map->node,
255 node_map->num_nodes + 1);
256 if (node_map->node == NULL) {
259 node = &node_map->node[node_map->num_nodes];
261 ret = ctdb_sock_addr_from_string(ip, &node->addr, false);
263 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
266 ctdb_sock_addr_set_port(&node->addr, CTDB_PORT);
269 node->capabilities = capabilities;
270 node->recovery_disabled = false;
271 node->recovery_substate = NULL;
273 node_map->num_nodes += 1;
276 if (node_map->num_nodes == 0) {
280 DEBUG(DEBUG_INFO, ("Parsing nodemap done\n"));
284 DEBUG(DEBUG_INFO, ("Parsing nodemap failed\n"));
289 /* Append a node to a node map with given address and flags */
290 static bool node_map_add(struct ctdb_node_map *nodemap,
291 const char *nstr, uint32_t flags)
295 struct ctdb_node_and_flags *n;
298 ret = ctdb_sock_addr_from_string(nstr, &addr, false);
300 fprintf(stderr, "Invalid IP address %s\n", nstr);
303 ctdb_sock_addr_set_port(&addr, CTDB_PORT);
306 nodemap->node = talloc_realloc(nodemap, nodemap->node,
307 struct ctdb_node_and_flags, num+1);
308 if (nodemap->node == NULL) {
312 n = &nodemap->node[num];
317 nodemap->num = num+1;
321 /* Read a nodes file into a node map */
322 static struct ctdb_node_map *ctdb_read_nodes_file(TALLOC_CTX *mem_ctx,
328 struct ctdb_node_map *nodemap;
330 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
331 if (nodemap == NULL) {
335 lines = file_lines_load(nlist, &nlines, 0, mem_ctx);
340 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
344 for (i=0; i<nlines; i++) {
350 /* strip leading spaces */
351 while((*node == ' ') || (*node == '\t')) {
357 /* strip trailing spaces */
359 ((node[len-1] == ' ') || (node[len-1] == '\t')))
369 /* A "deleted" node is a node that is
370 commented out in the nodes file. This is
371 used instead of removing a line, which
372 would cause subsequent nodes to change
374 flags = NODE_FLAGS_DELETED;
375 node = discard_const("0.0.0.0");
379 if (! node_map_add(nodemap, node, flags)) {
381 TALLOC_FREE(nodemap);
390 static struct ctdb_node_map *read_nodes_file(TALLOC_CTX *mem_ctx,
393 struct ctdb_node_map *nodemap;
394 char nodes_list[PATH_MAX];
395 const char *ctdb_base;
398 ctdb_base = getenv("CTDB_BASE");
399 if (ctdb_base == NULL) {
400 D_ERR("CTDB_BASE is not set\n");
404 /* read optional node-specific nodes file */
405 num = snprintf(nodes_list, sizeof(nodes_list),
406 "%s/nodes.%d", ctdb_base, pnn);
407 if (num == sizeof(nodes_list)) {
408 D_ERR("nodes file path too long\n");
411 nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
412 if (nodemap != NULL) {
413 /* Fake a load failure for an empty nodemap */
414 if (nodemap->num == 0) {
415 talloc_free(nodemap);
417 D_ERR("Failed to read nodes file \"%s\"\n", nodes_list);
424 /* read normal nodes file */
425 num = snprintf(nodes_list, sizeof(nodes_list), "%s/nodes", ctdb_base);
426 if (num == sizeof(nodes_list)) {
427 D_ERR("nodes file path too long\n");
430 nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
431 if (nodemap != NULL) {
435 DBG_ERR("Failed to read nodes file \"%s\"\n", nodes_list);
439 static struct interface_map *interfaces_init(TALLOC_CTX *mem_ctx)
441 struct interface_map *iface_map;
443 iface_map = talloc_zero(mem_ctx, struct interface_map);
444 if (iface_map == NULL) {
451 /* Read interfaces information. Same format as "ctdb ifaces -Y"
453 * :Name:LinkStatus:References:
458 static bool interfaces_parse(struct interface_map *iface_map)
462 while ((fgets(line, sizeof(line), stdin) != NULL)) {
465 char *tok, *t, *name;
466 struct interface *iface;
468 if (line[0] == '\n') {
472 /* Get rid of pesky newline */
473 if ((t = strchr(line, '\n')) != NULL) {
477 if (strcmp(line, ":Name:LinkStatus:References:") == 0) {
481 /* Leading colon... */
482 // tok = strtok(line, ":");
485 tok = strtok(line, ":");
487 fprintf(stderr, "bad line (%s) - missing name\n", line);
493 tok = strtok(NULL, ":");
495 fprintf(stderr, "bad line (%s) - missing link state\n",
499 link_state = (uint16_t)strtoul(tok, NULL, 0);
502 tok = strtok(NULL, ":");
504 fprintf(stderr, "bad line (%s) - missing references\n",
508 references = (uint32_t)strtoul(tok, NULL, 0);
510 iface_map->iface = talloc_realloc(iface_map, iface_map->iface,
513 if (iface_map->iface == NULL) {
517 iface = &iface_map->iface[iface_map->num];
519 iface->name = talloc_strdup(iface_map, name);
520 if (iface->name == NULL) {
523 iface->link_up = link_state;
524 iface->references = references;
529 if (iface_map->num == 0) {
533 DEBUG(DEBUG_INFO, ("Parsing interfaces done\n"));
537 fprintf(stderr, "Parsing interfaces failed\n");
541 static struct vnn_map *vnnmap_init(TALLOC_CTX *mem_ctx)
543 struct vnn_map *vnn_map;
545 vnn_map = talloc_zero(mem_ctx, struct vnn_map);
546 if (vnn_map == NULL) {
547 fprintf(stderr, "Memory error\n");
550 vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
551 vnn_map->generation = INVALID_GENERATION;
564 static bool vnnmap_parse(struct vnn_map *vnn_map)
568 while (fgets(line, sizeof(line), stdin) != NULL) {
572 if (line[0] == '\n') {
576 /* Get rid of pesky newline */
577 if ((t = strchr(line, '\n')) != NULL) {
581 n = (uint32_t) strtol(line, NULL, 0);
584 if (vnn_map->generation == INVALID_GENERATION) {
585 vnn_map->generation = n;
589 vnn_map->map = talloc_realloc(vnn_map, vnn_map->map, uint32_t,
591 if (vnn_map->map == NULL) {
592 fprintf(stderr, "Memory error\n");
596 vnn_map->map[vnn_map->size] = n;
600 if (vnn_map->size == 0) {
604 DEBUG(DEBUG_INFO, ("Parsing vnnmap done\n"));
608 fprintf(stderr, "Parsing vnnmap failed\n");
612 static bool reclock_parse(struct ctdbd_context *ctdb)
617 if (fgets(line, sizeof(line), stdin) == NULL) {
621 if (line[0] == '\n') {
625 /* Get rid of pesky newline */
626 if ((t = strchr(line, '\n')) != NULL) {
630 ctdb->reclock = talloc_strdup(ctdb, line);
631 if (ctdb->reclock == NULL) {
635 /* Swallow possible blank line following section. Picky
636 * compiler settings don't allow the return value to be
637 * ignored, so make the compiler happy.
639 if (fgets(line, sizeof(line), stdin) == NULL) {
642 DEBUG(DEBUG_INFO, ("Parsing reclock done\n"));
646 fprintf(stderr, "Parsing reclock failed\n");
650 static struct database_map *dbmap_init(TALLOC_CTX *mem_ctx,
653 struct database_map *db_map;
655 db_map = talloc_zero(mem_ctx, struct database_map);
656 if (db_map == NULL) {
660 db_map->dbdir = talloc_strdup(db_map, dbdir);
661 if (db_map->dbdir == NULL) {
669 /* Read a database map from stdin. Each line looks like:
670 * <ID> <NAME> [FLAGS] [SEQ_NUM]
671 * EOF or a blank line terminates input.
673 * By default, flags and seq_num are 0
676 static bool dbmap_parse(struct database_map *db_map)
680 while ((fgets(line, sizeof(line), stdin) != NULL)) {
683 uint32_t seq_num = 0;
688 if (line[0] == '\n') {
692 /* Get rid of pesky newline */
693 if ((t = strchr(line, '\n')) != NULL) {
698 tok = strtok(line, " \t");
700 fprintf(stderr, "bad line (%s) - missing ID\n", line);
703 id = (uint32_t)strtoul(tok, NULL, 0);
706 tok = strtok(NULL, " \t");
708 fprintf(stderr, "bad line (%s) - missing NAME\n", line);
711 name = talloc_strdup(db_map, tok);
717 tok = strtok(NULL, " \t");
718 while (tok != NULL) {
719 if (strcmp(tok, "PERSISTENT") == 0) {
720 flags |= CTDB_DB_FLAGS_PERSISTENT;
721 } else if (strcmp(tok, "STICKY") == 0) {
722 flags |= CTDB_DB_FLAGS_STICKY;
723 } else if (strcmp(tok, "READONLY") == 0) {
724 flags |= CTDB_DB_FLAGS_READONLY;
725 } else if (strcmp(tok, "REPLICATED") == 0) {
726 flags |= CTDB_DB_FLAGS_REPLICATED;
727 } else if (tok[0] >= '0'&& tok[0] <= '9') {
728 uint8_t nv = CTDB_DB_FLAGS_PERSISTENT |
729 CTDB_DB_FLAGS_REPLICATED;
731 if ((flags & nv) == 0) {
733 "seq_num for volatile db\n");
736 seq_num = (uint64_t)strtoull(tok, NULL, 0);
739 tok = strtok(NULL, " \t");
742 db = talloc_zero(db_map, struct database);
748 db->name = talloc_steal(db, name);
749 db->path = talloc_asprintf(db, "%s/%s", db_map->dbdir, name);
750 if (db->path == NULL) {
755 db->seq_num = seq_num;
757 DLIST_ADD_END(db_map->db, db);
760 if (db_map->db == NULL) {
764 DEBUG(DEBUG_INFO, ("Parsing dbmap done\n"));
768 DEBUG(DEBUG_INFO, ("Parsing dbmap failed\n"));
773 static struct database *database_find(struct database_map *db_map,
778 for (db = db_map->db; db != NULL; db = db->next) {
779 if (db->id == db_id) {
787 static int database_count(struct database_map *db_map)
792 for (db = db_map->db; db != NULL; db = db->next) {
799 static int database_flags(uint8_t db_flags)
803 if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
804 tdb_flags = TDB_DEFAULT;
806 /* volatile and replicated use the same flags */
807 tdb_flags = TDB_NOSYNC |
809 TDB_INCOMPATIBLE_HASH;
812 tdb_flags |= TDB_DISALLOW_NESTING;
817 static struct database *database_new(struct database_map *db_map,
818 const char *name, uint8_t flags)
824 db = talloc_zero(db_map, struct database);
829 db->name = talloc_strdup(db, name);
830 if (db->name == NULL) {
834 db->path = talloc_asprintf(db, "%s/%s", db_map->dbdir, name);
835 if (db->path == NULL) {
839 key.dsize = strlen(db->name) + 1;
840 key.dptr = discard_const(db->name);
842 db->id = tdb_jenkins_hash(&key);
845 tdb_flags = database_flags(flags);
847 db->tdb = tdb_open(db->path, 8192, tdb_flags, O_CREAT|O_RDWR, 0644);
848 if (db->tdb == NULL) {
849 DBG_ERR("tdb_open\n");
853 DLIST_ADD_END(db_map->db, db);
857 DBG_ERR("Memory error\n");
863 static int ltdb_store(struct database *db, TDB_DATA key,
864 struct ctdb_ltdb_header *header, TDB_DATA data)
867 bool db_volatile = true;
870 if (db->tdb == NULL) {
874 if ((db->flags & CTDB_DB_FLAGS_PERSISTENT) ||
875 (db->flags & CTDB_DB_FLAGS_REPLICATED)) {
879 if (data.dsize > 0) {
882 if (db_volatile && header->rsn == 0) {
890 rec[0].dsize = ctdb_ltdb_header_len(header);
891 rec[0].dptr = (uint8_t *)header;
893 rec[1].dsize = data.dsize;
894 rec[1].dptr = data.dptr;
896 ret = tdb_storev(db->tdb, key, rec, 2, TDB_REPLACE);
898 if (header->rsn > 0) {
899 ret = tdb_delete(db->tdb, key);
908 static int ltdb_fetch(struct database *db, TDB_DATA key,
909 struct ctdb_ltdb_header *header,
910 TALLOC_CTX *mem_ctx, TDB_DATA *data)
916 if (db->tdb == NULL) {
920 rec = tdb_fetch(db->tdb, key);
921 ret = ctdb_ltdb_header_pull(rec.dptr, rec.dsize, header, &np);
923 if (rec.dptr != NULL) {
927 *header = (struct ctdb_ltdb_header) {
933 ret = ltdb_store(db, key, header, tdb_null);
942 data->dsize = rec.dsize - ctdb_ltdb_header_len(header);
943 data->dptr = talloc_memdup(mem_ctx,
944 rec.dptr + ctdb_ltdb_header_len(header),
949 if (data->dptr == NULL) {
956 static int database_seqnum(struct database *db, uint64_t *seqnum)
958 const char *keyname = CTDB_DB_SEQNUM_KEY;
960 struct ctdb_ltdb_header header;
964 if (db->tdb == NULL) {
965 *seqnum = db->seq_num;
969 key.dptr = discard_const(keyname);
970 key.dsize = strlen(keyname) + 1;
972 ret = ltdb_fetch(db, key, &header, db, &data);
977 if (data.dsize == 0) {
982 ret = ctdb_uint64_pull(data.dptr, data.dsize, seqnum, &np);
983 talloc_free(data.dptr);
991 static int ltdb_transaction_update(uint32_t reqid,
992 struct ctdb_ltdb_header *no_header,
993 TDB_DATA key, TDB_DATA data,
996 struct database *db = (struct database *)private_data;
997 TALLOC_CTX *tmp_ctx = talloc_new(db);
998 struct ctdb_ltdb_header header = { 0 }, oldheader;
1002 if (db->tdb == NULL) {
1006 ret = ctdb_ltdb_header_extract(&data, &header);
1011 ret = ltdb_fetch(db, key, &oldheader, tmp_ctx, &olddata);
1016 if (olddata.dsize > 0) {
1017 if (oldheader.rsn > header.rsn ||
1018 (oldheader.rsn == header.rsn &&
1019 olddata.dsize != data.dsize)) {
1024 talloc_free(tmp_ctx);
1026 ret = ltdb_store(db, key, &header, data);
1030 static int ltdb_transaction(struct database *db,
1031 struct ctdb_rec_buffer *recbuf)
1035 if (db->tdb == NULL) {
1039 ret = tdb_transaction_start(db->tdb);
1044 ret = ctdb_rec_buffer_traverse(recbuf, ltdb_transaction_update, db);
1046 tdb_transaction_cancel(db->tdb);
1049 ret = tdb_transaction_commit(db->tdb);
1053 static bool public_ips_parse(struct ctdbd_context *ctdb,
1058 if (numnodes == 0) {
1059 D_ERR("Must initialise nodemap before public IPs\n");
1063 ctdb->known_ips = ipalloc_read_known_ips(ctdb, numnodes, false);
1065 status = (ctdb->known_ips != NULL && ctdb->known_ips->num != 0);
1068 D_INFO("Parsing public IPs done\n");
1070 D_INFO("Parsing public IPs failed\n");
1076 /* Read information about controls to fail. Format is:
1077 * <opcode> <pnn> {ERROR|TIMEOUT} <comment>
1079 static bool control_failures_parse(struct ctdbd_context *ctdb)
1083 while ((fgets(line, sizeof(line), stdin) != NULL)) {
1085 enum ctdb_controls opcode;
1088 const char *comment;
1089 struct fake_control_failure *failure = NULL;
1091 if (line[0] == '\n') {
1095 /* Get rid of pesky newline */
1096 if ((t = strchr(line, '\n')) != NULL) {
1101 tok = strtok(line, " \t");
1103 D_ERR("bad line (%s) - missing opcode\n", line);
1106 opcode = (enum ctdb_controls)strtoul(tok, NULL, 0);
1109 tok = strtok(NULL, " \t");
1111 D_ERR("bad line (%s) - missing PNN\n", line);
1114 pnn = (uint32_t)strtoul(tok, NULL, 0);
1117 tok = strtok(NULL, " \t");
1119 D_ERR("bad line (%s) - missing errno\n", line);
1122 error = talloc_strdup(ctdb, tok);
1123 if (error == NULL) {
1126 if (strcmp(error, "ERROR") != 0 &&
1127 strcmp(error, "TIMEOUT") != 0) {
1128 D_ERR("bad line (%s) "
1129 "- error must be \"ERROR\" or \"TIMEOUT\"\n",
1135 tok = strtok(NULL, "\n"); /* rest of line */
1137 D_ERR("bad line (%s) - missing comment\n", line);
1140 comment = talloc_strdup(ctdb, tok);
1141 if (comment == NULL) {
1145 failure = talloc_zero(ctdb, struct fake_control_failure);
1146 if (failure == NULL) {
1150 failure->opcode = opcode;
1152 failure->error = error;
1153 failure->comment = comment;
1155 DLIST_ADD(ctdb->control_failures, failure);
1158 if (ctdb->control_failures == NULL) {
1162 D_INFO("Parsing fake control failures done\n");
1166 D_INFO("Parsing fake control failures failed\n");
1170 static bool runstate_parse(struct ctdbd_context *ctdb)
1175 if (fgets(line, sizeof(line), stdin) == NULL) {
1179 if (line[0] == '\n') {
1183 /* Get rid of pesky newline */
1184 if ((t = strchr(line, '\n')) != NULL) {
1188 ctdb->runstate = ctdb_runstate_from_string(line);
1189 if (ctdb->runstate == CTDB_RUNSTATE_UNKNOWN) {
1193 /* Swallow possible blank line following section. Picky
1194 * compiler settings don't allow the return value to be
1195 * ignored, so make the compiler happy.
1197 if (fgets(line, sizeof(line), stdin) == NULL) {
1200 D_INFO("Parsing runstate done\n");
1204 D_ERR("Parsing runstate failed\n");
1212 static int ctdb_client_destructor(struct ctdb_client *client)
1214 DLIST_REMOVE(client->ctdb->client_list, client);
1218 static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
1221 struct ctdb_client *client;
1223 client = talloc_zero(client_state, struct ctdb_client);
1224 if (client == NULL) {
1228 client->ctdb = ctdb;
1229 client->pid = client_pid;
1230 client->state = client_state;
1232 DLIST_ADD(ctdb->client_list, client);
1233 talloc_set_destructor(client, ctdb_client_destructor);
1237 static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
1239 struct ctdb_client *client;
1241 for (client=ctdb->client_list; client != NULL; client=client->next) {
1242 if (client->pid == client_pid) {
1243 return client->state;
1251 * CTDB context setup
1254 static uint32_t new_generation(uint32_t old_generation)
1256 uint32_t generation;
1259 generation = random();
1260 if (generation != INVALID_GENERATION &&
1261 generation != old_generation) {
1269 static struct ctdbd_context *ctdbd_setup(TALLOC_CTX *mem_ctx,
1272 struct ctdbd_context *ctdb;
1277 ctdb = talloc_zero(mem_ctx, struct ctdbd_context);
1282 ctdb->node_map = nodemap_init(ctdb);
1283 if (ctdb->node_map == NULL) {
1287 ctdb->iface_map = interfaces_init(ctdb);
1288 if (ctdb->iface_map == NULL) {
1292 ctdb->vnn_map = vnnmap_init(ctdb);
1293 if (ctdb->vnn_map == NULL) {
1297 ctdb->db_map = dbmap_init(ctdb, dbdir);
1298 if (ctdb->db_map == NULL) {
1302 ret = srvid_init(ctdb, &ctdb->srv);
1307 ctdb->runstate = CTDB_RUNSTATE_RUNNING;
1309 while (fgets(line, sizeof(line), stdin) != NULL) {
1312 if ((t = strchr(line, '\n')) != NULL) {
1316 if (strcmp(line, "NODEMAP") == 0) {
1317 status = nodemap_parse(ctdb->node_map);
1318 } else if (strcmp(line, "IFACES") == 0) {
1319 status = interfaces_parse(ctdb->iface_map);
1320 } else if (strcmp(line, "VNNMAP") == 0) {
1321 status = vnnmap_parse(ctdb->vnn_map);
1322 } else if (strcmp(line, "DBMAP") == 0) {
1323 status = dbmap_parse(ctdb->db_map);
1324 } else if (strcmp(line, "PUBLICIPS") == 0) {
1325 status = public_ips_parse(ctdb,
1326 ctdb->node_map->num_nodes);
1327 } else if (strcmp(line, "RECLOCK") == 0) {
1328 status = reclock_parse(ctdb);
1329 } else if (strcmp(line, "CONTROLFAILS") == 0) {
1330 status = control_failures_parse(ctdb);
1331 } else if (strcmp(line, "RUNSTATE") == 0) {
1332 status = runstate_parse(ctdb);
1334 fprintf(stderr, "Unknown line %s\n", line);
1343 ctdb->start_time = tevent_timeval_current();
1344 ctdb->recovery_start_time = tevent_timeval_current();
1345 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1346 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
1347 ctdb->vnn_map->generation =
1348 new_generation(ctdb->vnn_map->generation);
1350 ctdb->recovery_end_time = tevent_timeval_current();
1352 ctdb->log_level = DEBUG_ERR;
1354 ctdb_tunable_set_defaults(&ctdb->tun_list);
1363 static bool ctdbd_verify(struct ctdbd_context *ctdb)
1368 if (ctdb->node_map->num_nodes == 0) {
1372 /* Make sure all the nodes are in order */
1373 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1374 node = &ctdb->node_map->node[i];
1375 if (node->pnn != i) {
1376 fprintf(stderr, "Expected node %u, found %u\n",
1382 node = &ctdb->node_map->node[ctdb->node_map->pnn];
1383 if (node->flags & NODE_FLAGS_DISCONNECTED) {
1384 DEBUG(DEBUG_INFO, ("Node disconnected, exiting\n"));
1395 struct recover_state {
1396 struct tevent_context *ev;
1397 struct ctdbd_context *ctdb;
1400 static int recover_check(struct tevent_req *req);
1401 static void recover_wait_done(struct tevent_req *subreq);
1402 static void recover_done(struct tevent_req *subreq);
1404 static struct tevent_req *recover_send(TALLOC_CTX *mem_ctx,
1405 struct tevent_context *ev,
1406 struct ctdbd_context *ctdb)
1408 struct tevent_req *req;
1409 struct recover_state *state;
1412 req = tevent_req_create(mem_ctx, &state, struct recover_state);
1420 ret = recover_check(req);
1422 tevent_req_error(req, ret);
1423 return tevent_req_post(req, ev);
1429 static int recover_check(struct tevent_req *req)
1431 struct recover_state *state = tevent_req_data(
1432 req, struct recover_state);
1433 struct ctdbd_context *ctdb = state->ctdb;
1434 struct tevent_req *subreq;
1435 bool recovery_disabled;
1438 recovery_disabled = false;
1439 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1440 if (ctdb->node_map->node[i].recovery_disabled) {
1441 recovery_disabled = true;
1446 subreq = tevent_wakeup_send(state, state->ev,
1447 tevent_timeval_current_ofs(1, 0));
1448 if (subreq == NULL) {
1452 if (recovery_disabled) {
1453 tevent_req_set_callback(subreq, recover_wait_done, req);
1455 ctdb->recovery_start_time = tevent_timeval_current();
1456 tevent_req_set_callback(subreq, recover_done, req);
1462 static void recover_wait_done(struct tevent_req *subreq)
1464 struct tevent_req *req = tevent_req_callback_data(
1465 subreq, struct tevent_req);
1469 status = tevent_wakeup_recv(subreq);
1470 TALLOC_FREE(subreq);
1472 tevent_req_error(req, EIO);
1476 ret = recover_check(req);
1478 tevent_req_error(req, ret);
1482 static void recover_done(struct tevent_req *subreq)
1484 struct tevent_req *req = tevent_req_callback_data(
1485 subreq, struct tevent_req);
1486 struct recover_state *state = tevent_req_data(
1487 req, struct recover_state);
1488 struct ctdbd_context *ctdb = state->ctdb;
1491 status = tevent_wakeup_recv(subreq);
1492 TALLOC_FREE(subreq);
1494 tevent_req_error(req, EIO);
1498 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1499 ctdb->recovery_end_time = tevent_timeval_current();
1500 ctdb->vnn_map->generation = new_generation(ctdb->vnn_map->generation);
1502 tevent_req_done(req);
1505 static bool recover_recv(struct tevent_req *req, int *perr)
1509 if (tevent_req_is_unix_error(req, &err)) {
1520 * Routines for ctdb_req_header
1523 static void header_fix_pnn(struct ctdb_req_header *header,
1524 struct ctdbd_context *ctdb)
1526 if (header->srcnode == CTDB_CURRENT_NODE) {
1527 header->srcnode = ctdb->node_map->pnn;
1530 if (header->destnode == CTDB_CURRENT_NODE) {
1531 header->destnode = ctdb->node_map->pnn;
1535 static struct ctdb_req_header header_reply_call(
1536 struct ctdb_req_header *header,
1537 struct ctdbd_context *ctdb)
1539 struct ctdb_req_header reply_header;
1541 reply_header = (struct ctdb_req_header) {
1542 .ctdb_magic = CTDB_MAGIC,
1543 .ctdb_version = CTDB_PROTOCOL,
1544 .generation = ctdb->vnn_map->generation,
1545 .operation = CTDB_REPLY_CALL,
1546 .destnode = header->srcnode,
1547 .srcnode = header->destnode,
1548 .reqid = header->reqid,
1551 return reply_header;
1554 static struct ctdb_req_header header_reply_control(
1555 struct ctdb_req_header *header,
1556 struct ctdbd_context *ctdb)
1558 struct ctdb_req_header reply_header;
1560 reply_header = (struct ctdb_req_header) {
1561 .ctdb_magic = CTDB_MAGIC,
1562 .ctdb_version = CTDB_PROTOCOL,
1563 .generation = ctdb->vnn_map->generation,
1564 .operation = CTDB_REPLY_CONTROL,
1565 .destnode = header->srcnode,
1566 .srcnode = header->destnode,
1567 .reqid = header->reqid,
1570 return reply_header;
1573 static struct ctdb_req_header header_reply_message(
1574 struct ctdb_req_header *header,
1575 struct ctdbd_context *ctdb)
1577 struct ctdb_req_header reply_header;
1579 reply_header = (struct ctdb_req_header) {
1580 .ctdb_magic = CTDB_MAGIC,
1581 .ctdb_version = CTDB_PROTOCOL,
1582 .generation = ctdb->vnn_map->generation,
1583 .operation = CTDB_REQ_MESSAGE,
1584 .destnode = header->srcnode,
1585 .srcnode = header->destnode,
1589 return reply_header;
1596 struct client_state {
1597 struct tevent_context *ev;
1599 struct ctdbd_context *ctdb;
1602 struct comm_context *comm;
1603 struct srvid_register_state *rstate;
1608 * Send replies to call, controls and messages
1611 static void client_reply_done(struct tevent_req *subreq);
1613 static void client_send_call(struct tevent_req *req,
1614 struct ctdb_req_header *header,
1615 struct ctdb_reply_call *reply)
1617 struct client_state *state = tevent_req_data(
1618 req, struct client_state);
1619 struct ctdbd_context *ctdb = state->ctdb;
1620 struct tevent_req *subreq;
1621 struct ctdb_req_header reply_header;
1623 size_t datalen, buflen;
1626 reply_header = header_reply_call(header, ctdb);
1628 datalen = ctdb_reply_call_len(&reply_header, reply);
1629 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1631 tevent_req_error(req, ret);
1635 ret = ctdb_reply_call_push(&reply_header, reply, buf, &buflen);
1637 tevent_req_error(req, ret);
1641 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1642 if (tevent_req_nomem(subreq, req)) {
1645 tevent_req_set_callback(subreq, client_reply_done, req);
1647 talloc_steal(subreq, buf);
1650 static void client_send_message(struct tevent_req *req,
1651 struct ctdb_req_header *header,
1652 struct ctdb_req_message_data *message)
1654 struct client_state *state = tevent_req_data(
1655 req, struct client_state);
1656 struct ctdbd_context *ctdb = state->ctdb;
1657 struct tevent_req *subreq;
1658 struct ctdb_req_header reply_header;
1660 size_t datalen, buflen;
1663 reply_header = header_reply_message(header, ctdb);
1665 datalen = ctdb_req_message_data_len(&reply_header, message);
1666 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1668 tevent_req_error(req, ret);
1672 ret = ctdb_req_message_data_push(&reply_header, message,
1675 tevent_req_error(req, ret);
1679 DEBUG(DEBUG_INFO, ("message srvid = 0x%"PRIx64"\n", message->srvid));
1681 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1682 if (tevent_req_nomem(subreq, req)) {
1685 tevent_req_set_callback(subreq, client_reply_done, req);
1687 talloc_steal(subreq, buf);
1690 static void client_send_control(struct tevent_req *req,
1691 struct ctdb_req_header *header,
1692 struct ctdb_reply_control *reply)
1694 struct client_state *state = tevent_req_data(
1695 req, struct client_state);
1696 struct ctdbd_context *ctdb = state->ctdb;
1697 struct tevent_req *subreq;
1698 struct ctdb_req_header reply_header;
1700 size_t datalen, buflen;
1703 reply_header = header_reply_control(header, ctdb);
1705 datalen = ctdb_reply_control_len(&reply_header, reply);
1706 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1708 tevent_req_error(req, ret);
1712 ret = ctdb_reply_control_push(&reply_header, reply, buf, &buflen);
1714 tevent_req_error(req, ret);
1718 DEBUG(DEBUG_INFO, ("reply opcode = %u\n", reply->rdata.opcode));
1720 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1721 if (tevent_req_nomem(subreq, req)) {
1724 tevent_req_set_callback(subreq, client_reply_done, req);
1726 talloc_steal(subreq, buf);
1729 static void client_reply_done(struct tevent_req *subreq)
1731 struct tevent_req *req = tevent_req_callback_data(
1732 subreq, struct tevent_req);
1736 status = comm_write_recv(subreq, &ret);
1737 TALLOC_FREE(subreq);
1739 tevent_req_error(req, ret);
1744 * Handling protocol - controls
1747 static void control_process_exists(TALLOC_CTX *mem_ctx,
1748 struct tevent_req *req,
1749 struct ctdb_req_header *header,
1750 struct ctdb_req_control *request)
1752 struct client_state *state = tevent_req_data(
1753 req, struct client_state);
1754 struct ctdbd_context *ctdb = state->ctdb;
1755 struct client_state *cstate;
1756 struct ctdb_reply_control reply;
1758 reply.rdata.opcode = request->opcode;
1760 cstate = client_find(ctdb, request->rdata.data.pid);
1761 if (cstate == NULL) {
1763 reply.errmsg = "No client for PID";
1765 reply.status = kill(request->rdata.data.pid, 0);
1766 reply.errmsg = NULL;
1769 client_send_control(req, header, &reply);
1772 static void control_ping(TALLOC_CTX *mem_ctx,
1773 struct tevent_req *req,
1774 struct ctdb_req_header *header,
1775 struct ctdb_req_control *request)
1777 struct client_state *state = tevent_req_data(
1778 req, struct client_state);
1779 struct ctdbd_context *ctdb = state->ctdb;
1780 struct ctdb_reply_control reply;
1782 reply.rdata.opcode = request->opcode;
1783 reply.status = ctdb->num_clients;
1784 reply.errmsg = NULL;
1786 client_send_control(req, header, &reply);
1789 static void control_getdbpath(TALLOC_CTX *mem_ctx,
1790 struct tevent_req *req,
1791 struct ctdb_req_header *header,
1792 struct ctdb_req_control *request)
1794 struct client_state *state = tevent_req_data(
1795 req, struct client_state);
1796 struct ctdbd_context *ctdb = state->ctdb;
1797 struct ctdb_reply_control reply;
1798 struct database *db;
1800 reply.rdata.opcode = request->opcode;
1802 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1804 reply.status = ENOENT;
1805 reply.errmsg = "Database not found";
1807 reply.rdata.data.db_path =
1808 talloc_strdup(mem_ctx, db->path);
1809 if (reply.rdata.data.db_path == NULL) {
1810 reply.status = ENOMEM;
1811 reply.errmsg = "Memory error";
1814 reply.errmsg = NULL;
1818 client_send_control(req, header, &reply);
1821 static void control_getvnnmap(TALLOC_CTX *mem_ctx,
1822 struct tevent_req *req,
1823 struct ctdb_req_header *header,
1824 struct ctdb_req_control *request)
1826 struct client_state *state = tevent_req_data(
1827 req, struct client_state);
1828 struct ctdbd_context *ctdb = state->ctdb;
1829 struct ctdb_reply_control reply;
1830 struct ctdb_vnn_map *vnnmap;
1832 reply.rdata.opcode = request->opcode;
1834 vnnmap = talloc_zero(mem_ctx, struct ctdb_vnn_map);
1835 if (vnnmap == NULL) {
1836 reply.status = ENOMEM;
1837 reply.errmsg = "Memory error";
1839 vnnmap->generation = ctdb->vnn_map->generation;
1840 vnnmap->size = ctdb->vnn_map->size;
1841 vnnmap->map = ctdb->vnn_map->map;
1843 reply.rdata.data.vnnmap = vnnmap;
1845 reply.errmsg = NULL;
1848 client_send_control(req, header, &reply);
1851 static void control_get_debug(TALLOC_CTX *mem_ctx,
1852 struct tevent_req *req,
1853 struct ctdb_req_header *header,
1854 struct ctdb_req_control *request)
1856 struct client_state *state = tevent_req_data(
1857 req, struct client_state);
1858 struct ctdbd_context *ctdb = state->ctdb;
1859 struct ctdb_reply_control reply;
1861 reply.rdata.opcode = request->opcode;
1862 reply.rdata.data.loglevel = (uint32_t)ctdb->log_level;
1864 reply.errmsg = NULL;
1866 client_send_control(req, header, &reply);
1869 static void control_set_debug(TALLOC_CTX *mem_ctx,
1870 struct tevent_req *req,
1871 struct ctdb_req_header *header,
1872 struct ctdb_req_control *request)
1874 struct client_state *state = tevent_req_data(
1875 req, struct client_state);
1876 struct ctdbd_context *ctdb = state->ctdb;
1877 struct ctdb_reply_control reply;
1879 ctdb->log_level = (int)request->rdata.data.loglevel;
1881 reply.rdata.opcode = request->opcode;
1883 reply.errmsg = NULL;
1885 client_send_control(req, header, &reply);
1888 static void control_get_dbmap(TALLOC_CTX *mem_ctx,
1889 struct tevent_req *req,
1890 struct ctdb_req_header *header,
1891 struct ctdb_req_control *request)
1893 struct client_state *state = tevent_req_data(
1894 req, struct client_state);
1895 struct ctdbd_context *ctdb = state->ctdb;
1896 struct ctdb_reply_control reply;
1897 struct ctdb_dbid_map *dbmap;
1898 struct database *db;
1901 reply.rdata.opcode = request->opcode;
1903 dbmap = talloc_zero(mem_ctx, struct ctdb_dbid_map);
1904 if (dbmap == NULL) {
1908 dbmap->num = database_count(ctdb->db_map);
1909 dbmap->dbs = talloc_zero_array(dbmap, struct ctdb_dbid, dbmap->num);
1910 if (dbmap->dbs == NULL) {
1914 db = ctdb->db_map->db;
1915 for (i = 0; i < dbmap->num; i++) {
1916 dbmap->dbs[i] = (struct ctdb_dbid) {
1924 reply.rdata.data.dbmap = dbmap;
1926 reply.errmsg = NULL;
1927 client_send_control(req, header, &reply);
1932 reply.errmsg = "Memory error";
1933 client_send_control(req, header, &reply);
1936 static void control_get_recmode(TALLOC_CTX *mem_ctx,
1937 struct tevent_req *req,
1938 struct ctdb_req_header *header,
1939 struct ctdb_req_control *request)
1941 struct client_state *state = tevent_req_data(
1942 req, struct client_state);
1943 struct ctdbd_context *ctdb = state->ctdb;
1944 struct ctdb_reply_control reply;
1946 reply.rdata.opcode = request->opcode;
1947 reply.status = ctdb->vnn_map->recmode;
1948 reply.errmsg = NULL;
1950 client_send_control(req, header, &reply);
1953 struct set_recmode_state {
1954 struct tevent_req *req;
1955 struct ctdbd_context *ctdb;
1956 struct ctdb_req_header header;
1957 struct ctdb_reply_control reply;
1960 static void set_recmode_callback(struct tevent_req *subreq)
1962 struct set_recmode_state *substate = tevent_req_callback_data(
1963 subreq, struct set_recmode_state);
1967 status = recover_recv(subreq, &ret);
1968 TALLOC_FREE(subreq);
1970 substate->reply.status = ret;
1971 substate->reply.errmsg = "recovery failed";
1973 substate->reply.status = 0;
1974 substate->reply.errmsg = NULL;
1977 client_send_control(substate->req, &substate->header, &substate->reply);
1978 talloc_free(substate);
1981 static void control_set_recmode(TALLOC_CTX *mem_ctx,
1982 struct tevent_req *req,
1983 struct ctdb_req_header *header,
1984 struct ctdb_req_control *request)
1986 struct client_state *state = tevent_req_data(
1987 req, struct client_state);
1988 struct tevent_req *subreq;
1989 struct ctdbd_context *ctdb = state->ctdb;
1990 struct set_recmode_state *substate;
1991 struct ctdb_reply_control reply;
1993 reply.rdata.opcode = request->opcode;
1995 if (request->rdata.data.recmode == CTDB_RECOVERY_NORMAL) {
1997 reply.errmsg = "Client cannot set recmode to NORMAL";
2001 substate = talloc_zero(ctdb, struct set_recmode_state);
2002 if (substate == NULL) {
2004 reply.errmsg = "Memory error";
2008 substate->req = req;
2009 substate->ctdb = ctdb;
2010 substate->header = *header;
2011 substate->reply.rdata.opcode = request->opcode;
2013 subreq = recover_send(substate, state->ev, state->ctdb);
2014 if (subreq == NULL) {
2015 talloc_free(substate);
2018 tevent_req_set_callback(subreq, set_recmode_callback, substate);
2020 ctdb->vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
2024 client_send_control(req, header, &reply);
2028 static void control_db_attach(TALLOC_CTX *mem_ctx,
2029 struct tevent_req *req,
2030 struct ctdb_req_header *header,
2031 struct ctdb_req_control *request)
2033 struct client_state *state = tevent_req_data(
2034 req, struct client_state);
2035 struct ctdbd_context *ctdb = state->ctdb;
2036 struct ctdb_reply_control reply;
2037 struct database *db;
2039 reply.rdata.opcode = request->opcode;
2041 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
2042 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
2047 db = database_new(ctdb->db_map, request->rdata.data.db_name, 0);
2050 reply.errmsg = "Failed to attach database";
2051 client_send_control(req, header, &reply);
2056 reply.rdata.data.db_id = db->id;
2058 reply.errmsg = NULL;
2059 client_send_control(req, header, &reply);
2062 static void srvid_handler_done(struct tevent_req *subreq);
2064 static void srvid_handler(uint64_t srvid, TDB_DATA data, void *private_data)
2066 struct client_state *state = talloc_get_type_abort(
2067 private_data, struct client_state);
2068 struct ctdbd_context *ctdb = state->ctdb;
2069 struct tevent_req *subreq;
2070 struct ctdb_req_header request_header;
2071 struct ctdb_req_message_data message;
2073 size_t datalen, buflen;
2076 request_header = (struct ctdb_req_header) {
2077 .ctdb_magic = CTDB_MAGIC,
2078 .ctdb_version = CTDB_PROTOCOL,
2079 .generation = ctdb->vnn_map->generation,
2080 .operation = CTDB_REQ_MESSAGE,
2081 .destnode = state->pnn,
2082 .srcnode = ctdb->node_map->recmaster,
2086 message = (struct ctdb_req_message_data) {
2091 datalen = ctdb_req_message_data_len(&request_header, &message);
2092 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
2097 ret = ctdb_req_message_data_push(&request_header,
2106 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
2107 if (subreq == NULL) {
2111 tevent_req_set_callback(subreq, srvid_handler_done, state);
2113 talloc_steal(subreq, buf);
2116 static void srvid_handler_done(struct tevent_req *subreq)
2118 struct client_state *state = tevent_req_callback_data(
2119 subreq, struct client_state);
2123 ok = comm_write_recv(subreq, &ret);
2124 TALLOC_FREE(subreq);
2127 ("Failed to dispatch message to client pid=%u, ret=%d\n",
2133 static void control_register_srvid(TALLOC_CTX *mem_ctx,
2134 struct tevent_req *req,
2135 struct ctdb_req_header *header,
2136 struct ctdb_req_control *request)
2138 struct client_state *state = tevent_req_data(
2139 req, struct client_state);
2140 struct ctdbd_context *ctdb = state->ctdb;
2141 struct ctdb_reply_control reply;
2144 reply.rdata.opcode = request->opcode;
2146 ret = srvid_register(ctdb->srv, state, request->srvid,
2147 srvid_handler, state);
2150 reply.errmsg = "Memory error";
2154 DEBUG(DEBUG_INFO, ("Register srvid 0x%"PRIx64"\n", request->srvid));
2157 reply.errmsg = NULL;
2160 client_send_control(req, header, &reply);
2163 static void control_deregister_srvid(TALLOC_CTX *mem_ctx,
2164 struct tevent_req *req,
2165 struct ctdb_req_header *header,
2166 struct ctdb_req_control *request)
2168 struct client_state *state = tevent_req_data(
2169 req, struct client_state);
2170 struct ctdbd_context *ctdb = state->ctdb;
2171 struct ctdb_reply_control reply;
2174 reply.rdata.opcode = request->opcode;
2176 ret = srvid_deregister(ctdb->srv, request->srvid, state);
2179 reply.errmsg = "srvid not registered";
2183 DEBUG(DEBUG_INFO, ("Deregister srvid 0x%"PRIx64"\n", request->srvid));
2186 reply.errmsg = NULL;
2189 client_send_control(req, header, &reply);
2192 static void control_get_dbname(TALLOC_CTX *mem_ctx,
2193 struct tevent_req *req,
2194 struct ctdb_req_header *header,
2195 struct ctdb_req_control *request)
2197 struct client_state *state = tevent_req_data(
2198 req, struct client_state);
2199 struct ctdbd_context *ctdb = state->ctdb;
2200 struct ctdb_reply_control reply;
2201 struct database *db;
2203 reply.rdata.opcode = request->opcode;
2205 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2207 reply.status = ENOENT;
2208 reply.errmsg = "Database not found";
2210 reply.rdata.data.db_name = talloc_strdup(mem_ctx, db->name);
2211 if (reply.rdata.data.db_name == NULL) {
2212 reply.status = ENOMEM;
2213 reply.errmsg = "Memory error";
2216 reply.errmsg = NULL;
2220 client_send_control(req, header, &reply);
2223 static void control_get_pid(TALLOC_CTX *mem_ctx,
2224 struct tevent_req *req,
2225 struct ctdb_req_header *header,
2226 struct ctdb_req_control *request)
2228 struct ctdb_reply_control reply;
2230 reply.rdata.opcode = request->opcode;
2231 reply.status = getpid();
2232 reply.errmsg = NULL;
2234 client_send_control(req, header, &reply);
2237 static void control_get_pnn(TALLOC_CTX *mem_ctx,
2238 struct tevent_req *req,
2239 struct ctdb_req_header *header,
2240 struct ctdb_req_control *request)
2242 struct ctdb_reply_control reply;
2244 reply.rdata.opcode = request->opcode;
2245 reply.status = header->destnode;
2246 reply.errmsg = NULL;
2248 client_send_control(req, header, &reply);
2251 static void control_shutdown(TALLOC_CTX *mem_ctx,
2252 struct tevent_req *req,
2253 struct ctdb_req_header *hdr,
2254 struct ctdb_req_control *request)
2256 struct client_state *state = tevent_req_data(
2257 req, struct client_state);
2262 static void control_set_tunable(TALLOC_CTX *mem_ctx,
2263 struct tevent_req *req,
2264 struct ctdb_req_header *header,
2265 struct ctdb_req_control *request)
2267 struct client_state *state = tevent_req_data(
2268 req, struct client_state);
2269 struct ctdbd_context *ctdb = state->ctdb;
2270 struct ctdb_reply_control reply;
2273 reply.rdata.opcode = request->opcode;
2274 reply.errmsg = NULL;
2276 ret = ctdb_tunable_set_value(&ctdb->tun_list,
2277 request->rdata.data.tunable->name,
2278 request->rdata.data.tunable->value,
2282 } else if (obsolete) {
2288 client_send_control(req, header, &reply);
2291 static void control_get_tunable(TALLOC_CTX *mem_ctx,
2292 struct tevent_req *req,
2293 struct ctdb_req_header *header,
2294 struct ctdb_req_control *request)
2296 struct client_state *state = tevent_req_data(
2297 req, struct client_state);
2298 struct ctdbd_context *ctdb = state->ctdb;
2299 struct ctdb_reply_control reply;
2303 reply.rdata.opcode = request->opcode;
2304 reply.errmsg = NULL;
2306 ret = ctdb_tunable_get_value(&ctdb->tun_list,
2307 request->rdata.data.tun_var, &value);
2311 reply.rdata.data.tun_value = value;
2315 client_send_control(req, header, &reply);
2318 static void control_list_tunables(TALLOC_CTX *mem_ctx,
2319 struct tevent_req *req,
2320 struct ctdb_req_header *header,
2321 struct ctdb_req_control *request)
2323 struct ctdb_reply_control reply;
2324 struct ctdb_var_list *var_list;
2326 reply.rdata.opcode = request->opcode;
2327 reply.errmsg = NULL;
2329 var_list = ctdb_tunable_names(mem_ctx);
2330 if (var_list == NULL) {
2333 reply.rdata.data.tun_var_list = var_list;
2337 client_send_control(req, header, &reply);
2340 static void control_modify_flags(TALLOC_CTX *mem_ctx,
2341 struct tevent_req *req,
2342 struct ctdb_req_header *header,
2343 struct ctdb_req_control *request)
2345 struct client_state *state = tevent_req_data(
2346 req, struct client_state);
2347 struct ctdbd_context *ctdb = state->ctdb;
2348 struct ctdb_node_flag_change *change = request->rdata.data.flag_change;
2349 struct ctdb_reply_control reply;
2352 reply.rdata.opcode = request->opcode;
2354 if ((change->old_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) ||
2355 (change->new_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2357 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
2358 reply.status = EINVAL;
2359 reply.errmsg = "Failed to MODIFY_FLAGS";
2360 client_send_control(req, header, &reply);
2364 /* There's all sorts of broadcast weirdness here. Only change
2365 * the specified node, not the destination node of the
2367 node = &ctdb->node_map->node[change->pnn];
2370 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0 &&
2371 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2372 DEBUG(DEBUG_INFO,("Disabling node %d\n", header->destnode));
2373 node->flags |= NODE_FLAGS_PERMANENTLY_DISABLED;
2378 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0 &&
2379 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0) {
2380 DEBUG(DEBUG_INFO,("Enabling node %d\n", header->destnode));
2381 node->flags &= ~NODE_FLAGS_PERMANENTLY_DISABLED;
2385 DEBUG(DEBUG_INFO, ("Flags unchanged for node %d\n", header->destnode));
2389 reply.errmsg = NULL;
2390 client_send_control(req, header, &reply);
2393 static void control_get_all_tunables(TALLOC_CTX *mem_ctx,
2394 struct tevent_req *req,
2395 struct ctdb_req_header *header,
2396 struct ctdb_req_control *request)
2398 struct client_state *state = tevent_req_data(
2399 req, struct client_state);
2400 struct ctdbd_context *ctdb = state->ctdb;
2401 struct ctdb_reply_control reply;
2403 reply.rdata.opcode = request->opcode;
2404 reply.rdata.data.tun_list = &ctdb->tun_list;
2406 reply.errmsg = NULL;
2408 client_send_control(req, header, &reply);
2411 static void control_db_attach_persistent(TALLOC_CTX *mem_ctx,
2412 struct tevent_req *req,
2413 struct ctdb_req_header *header,
2414 struct ctdb_req_control *request)
2416 struct client_state *state = tevent_req_data(
2417 req, struct client_state);
2418 struct ctdbd_context *ctdb = state->ctdb;
2419 struct ctdb_reply_control reply;
2420 struct database *db;
2422 reply.rdata.opcode = request->opcode;
2424 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
2425 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
2430 db = database_new(ctdb->db_map, request->rdata.data.db_name,
2431 CTDB_DB_FLAGS_PERSISTENT);
2434 reply.errmsg = "Failed to attach database";
2435 client_send_control(req, header, &reply);
2440 reply.rdata.data.db_id = db->id;
2442 reply.errmsg = NULL;
2443 client_send_control(req, header, &reply);
2446 static void control_uptime(TALLOC_CTX *mem_ctx,
2447 struct tevent_req *req,
2448 struct ctdb_req_header *header,
2449 struct ctdb_req_control *request)
2451 struct client_state *state = tevent_req_data(
2452 req, struct client_state);
2453 struct ctdbd_context *ctdb = state->ctdb;
2454 struct ctdb_reply_control reply;
2455 struct ctdb_uptime *uptime;;
2457 reply.rdata.opcode = request->opcode;
2459 uptime = talloc_zero(mem_ctx, struct ctdb_uptime);
2460 if (uptime == NULL) {
2464 uptime->current_time = tevent_timeval_current();
2465 uptime->ctdbd_start_time = ctdb->start_time;
2466 uptime->last_recovery_started = ctdb->recovery_start_time;
2467 uptime->last_recovery_finished = ctdb->recovery_end_time;
2469 reply.rdata.data.uptime = uptime;
2471 reply.errmsg = NULL;
2472 client_send_control(req, header, &reply);
2477 reply.errmsg = "Memory error";
2478 client_send_control(req, header, &reply);
2481 static void control_reload_nodes_file(TALLOC_CTX *mem_ctx,
2482 struct tevent_req *req,
2483 struct ctdb_req_header *header,
2484 struct ctdb_req_control *request)
2486 struct client_state *state = tevent_req_data(
2487 req, struct client_state);
2488 struct ctdbd_context *ctdb = state->ctdb;
2489 struct ctdb_reply_control reply;
2490 struct ctdb_node_map *nodemap;
2491 struct node_map *node_map = ctdb->node_map;
2494 reply.rdata.opcode = request->opcode;
2496 nodemap = read_nodes_file(mem_ctx, header->destnode);
2497 if (nodemap == NULL) {
2501 for (i=0; i<nodemap->num; i++) {
2504 if (i < node_map->num_nodes &&
2505 ctdb_sock_addr_same(&nodemap->node[i].addr,
2506 &node_map->node[i].addr)) {
2510 if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
2513 node = &node_map->node[i];
2515 node->flags |= NODE_FLAGS_DELETED;
2516 ret = ctdb_sock_addr_from_string("0.0.0.0", &node->addr,
2519 /* Can't happen, but Coverity... */
2526 if (i < node_map->num_nodes &&
2527 node_map->node[i].flags & NODE_FLAGS_DELETED) {
2528 node = &node_map->node[i];
2530 node->flags &= ~NODE_FLAGS_DELETED;
2531 node->addr = nodemap->node[i].addr;
2536 node_map->node = talloc_realloc(node_map, node_map->node,
2538 node_map->num_nodes+1);
2539 if (node_map->node == NULL) {
2542 node = &node_map->node[node_map->num_nodes];
2544 node->addr = nodemap->node[i].addr;
2545 node->pnn = nodemap->node[i].pnn;
2547 node->capabilities = CTDB_CAP_DEFAULT;
2548 node->recovery_disabled = false;
2549 node->recovery_substate = NULL;
2551 node_map->num_nodes += 1;
2554 talloc_free(nodemap);
2557 reply.errmsg = NULL;
2558 client_send_control(req, header, &reply);
2563 reply.errmsg = "Memory error";
2564 client_send_control(req, header, &reply);
2567 static void control_get_capabilities(TALLOC_CTX *mem_ctx,
2568 struct tevent_req *req,
2569 struct ctdb_req_header *header,
2570 struct ctdb_req_control *request)
2572 struct client_state *state = tevent_req_data(
2573 req, struct client_state);
2574 struct ctdbd_context *ctdb = state->ctdb;
2575 struct ctdb_reply_control reply;
2579 reply.rdata.opcode = request->opcode;
2581 node = &ctdb->node_map->node[header->destnode];
2582 caps = node->capabilities;
2584 if (node->flags & NODE_FLAGS_FAKE_TIMEOUT) {
2585 /* Don't send reply */
2589 reply.rdata.data.caps = caps;
2591 reply.errmsg = NULL;
2593 client_send_control(req, header, &reply);
2596 static void control_release_ip(TALLOC_CTX *mem_ctx,
2597 struct tevent_req *req,
2598 struct ctdb_req_header *header,
2599 struct ctdb_req_control *request)
2601 struct client_state *state = tevent_req_data(
2602 req, struct client_state);
2603 struct ctdbd_context *ctdb = state->ctdb;
2604 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2605 struct ctdb_reply_control reply;
2606 struct ctdb_public_ip_list *ips = NULL;
2607 struct ctdb_public_ip *t = NULL;
2610 reply.rdata.opcode = request->opcode;
2612 if (ctdb->known_ips == NULL) {
2613 D_INFO("RELEASE_IP %s - not a public IP\n",
2614 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2618 ips = &ctdb->known_ips[header->destnode];
2621 for (i = 0; i < ips->num; i++) {
2622 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2628 D_INFO("RELEASE_IP %s - not a public IP\n",
2629 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2633 if (t->pnn != header->destnode) {
2634 if (header->destnode == ip->pnn) {
2635 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2636 ctdb_sock_addr_to_string(mem_ctx,
2640 reply.errmsg = "RELEASE_IP to TAKE_IP node";
2641 client_send_control(req, header, &reply);
2645 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2646 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2650 D_NOTICE("RELEASE_IP %s - to node %d\n",
2651 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2658 reply.errmsg = NULL;
2659 client_send_control(req, header, &reply);
2662 static void control_takeover_ip(TALLOC_CTX *mem_ctx,
2663 struct tevent_req *req,
2664 struct ctdb_req_header *header,
2665 struct ctdb_req_control *request)
2667 struct client_state *state = tevent_req_data(
2668 req, struct client_state);
2669 struct ctdbd_context *ctdb = state->ctdb;
2670 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2671 struct ctdb_reply_control reply;
2672 struct ctdb_public_ip_list *ips = NULL;
2673 struct ctdb_public_ip *t = NULL;
2676 reply.rdata.opcode = request->opcode;
2678 if (ctdb->known_ips == NULL) {
2679 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2680 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2684 ips = &ctdb->known_ips[header->destnode];
2687 for (i = 0; i < ips->num; i++) {
2688 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2694 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2695 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2699 if (t->pnn == header->destnode) {
2700 D_INFO("TAKEOVER_IP %s - redundant\n",
2701 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2703 D_NOTICE("TAKEOVER_IP %s\n",
2704 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2710 reply.errmsg = NULL;
2711 client_send_control(req, header, &reply);
2714 static void control_get_public_ips(TALLOC_CTX *mem_ctx,
2715 struct tevent_req *req,
2716 struct ctdb_req_header *header,
2717 struct ctdb_req_control *request)
2719 struct client_state *state = tevent_req_data(
2720 req, struct client_state);
2721 struct ctdbd_context *ctdb = state->ctdb;
2722 struct ctdb_reply_control reply;
2723 struct ctdb_public_ip_list *ips = NULL;
2725 reply.rdata.opcode = request->opcode;
2727 if (ctdb->known_ips == NULL) {
2728 /* No IPs defined so create a dummy empty struct and ship it */
2729 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2731 reply.status = ENOMEM;
2732 reply.errmsg = "Memory error";
2738 ips = &ctdb->known_ips[header->destnode];
2740 if (request->flags & CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE) {
2741 /* If runstate is not RUNNING or a node is then return
2742 * no available IPs. Don't worry about interface
2743 * states here - we're not faking down to that level.
2745 uint32_t flags = ctdb->node_map->node[header->destnode].flags;
2746 if (ctdb->runstate != CTDB_RUNSTATE_RUNNING ||
2747 ((flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED)) != 0)) {
2748 /* No available IPs: return dummy empty struct */
2749 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2751 reply.status = ENOMEM;
2752 reply.errmsg = "Memory error";
2759 reply.rdata.data.pubip_list = ips;
2761 reply.errmsg = NULL;
2764 client_send_control(req, header, &reply);
2767 static void control_get_nodemap(TALLOC_CTX *mem_ctx,
2768 struct tevent_req *req,
2769 struct ctdb_req_header *header,
2770 struct ctdb_req_control *request)
2772 struct client_state *state = tevent_req_data(
2773 req, struct client_state);
2774 struct ctdbd_context *ctdb = state->ctdb;
2775 struct ctdb_reply_control reply;
2776 struct ctdb_node_map *nodemap;
2780 reply.rdata.opcode = request->opcode;
2782 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
2783 if (nodemap == NULL) {
2787 nodemap->num = ctdb->node_map->num_nodes;
2788 nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2790 if (nodemap->node == NULL) {
2794 for (i=0; i<nodemap->num; i++) {
2795 node = &ctdb->node_map->node[i];
2796 nodemap->node[i] = (struct ctdb_node_and_flags) {
2798 .flags = node->flags,
2803 reply.rdata.data.nodemap = nodemap;
2805 reply.errmsg = NULL;
2806 client_send_control(req, header, &reply);
2811 reply.errmsg = "Memory error";
2812 client_send_control(req, header, &reply);
2815 static void control_get_reclock_file(TALLOC_CTX *mem_ctx,
2816 struct tevent_req *req,
2817 struct ctdb_req_header *header,
2818 struct ctdb_req_control *request)
2820 struct client_state *state = tevent_req_data(
2821 req, struct client_state);
2822 struct ctdbd_context *ctdb = state->ctdb;
2823 struct ctdb_reply_control reply;
2825 reply.rdata.opcode = request->opcode;
2827 if (ctdb->reclock != NULL) {
2828 reply.rdata.data.reclock_file =
2829 talloc_strdup(mem_ctx, ctdb->reclock);
2830 if (reply.rdata.data.reclock_file == NULL) {
2831 reply.status = ENOMEM;
2832 reply.errmsg = "Memory error";
2836 reply.rdata.data.reclock_file = NULL;
2840 reply.errmsg = NULL;
2843 client_send_control(req, header, &reply);
2846 static void control_stop_node(TALLOC_CTX *mem_ctx,
2847 struct tevent_req *req,
2848 struct ctdb_req_header *header,
2849 struct ctdb_req_control *request)
2851 struct client_state *state = tevent_req_data(
2852 req, struct client_state);
2853 struct ctdbd_context *ctdb = state->ctdb;
2854 struct ctdb_reply_control reply;
2856 reply.rdata.opcode = request->opcode;
2858 DEBUG(DEBUG_INFO, ("Stopping node\n"));
2859 ctdb->node_map->node[header->destnode].flags |= NODE_FLAGS_STOPPED;
2862 reply.errmsg = NULL;
2864 client_send_control(req, header, &reply);
2868 static void control_continue_node(TALLOC_CTX *mem_ctx,
2869 struct tevent_req *req,
2870 struct ctdb_req_header *header,
2871 struct ctdb_req_control *request)
2873 struct client_state *state = tevent_req_data(
2874 req, struct client_state);
2875 struct ctdbd_context *ctdb = state->ctdb;
2876 struct ctdb_reply_control reply;
2878 reply.rdata.opcode = request->opcode;
2880 DEBUG(DEBUG_INFO, ("Continue node\n"));
2881 ctdb->node_map->node[header->destnode].flags &= ~NODE_FLAGS_STOPPED;
2884 reply.errmsg = NULL;
2886 client_send_control(req, header, &reply);
2890 static void set_ban_state_callback(struct tevent_req *subreq)
2892 struct node *node = tevent_req_callback_data(
2893 subreq, struct node);
2896 status = tevent_wakeup_recv(subreq);
2897 TALLOC_FREE(subreq);
2899 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2902 node->flags &= ~NODE_FLAGS_BANNED;
2905 static void control_set_ban_state(TALLOC_CTX *mem_ctx,
2906 struct tevent_req *req,
2907 struct ctdb_req_header *header,
2908 struct ctdb_req_control *request)
2910 struct client_state *state = tevent_req_data(
2911 req, struct client_state);
2912 struct tevent_req *subreq;
2913 struct ctdbd_context *ctdb = state->ctdb;
2914 struct ctdb_ban_state *ban = request->rdata.data.ban_state;
2915 struct ctdb_reply_control reply;
2918 reply.rdata.opcode = request->opcode;
2920 if (ban->pnn != header->destnode) {
2922 ("SET_BAN_STATE control for PNN %d rejected\n",
2924 reply.status = EINVAL;
2928 node = &ctdb->node_map->node[header->destnode];
2930 if (ban->time == 0) {
2931 DEBUG(DEBUG_INFO,("Unbanning this node\n"));
2932 node->flags &= ~NODE_FLAGS_BANNED;
2936 subreq = tevent_wakeup_send(ctdb->node_map, state->ev,
2937 tevent_timeval_current_ofs(
2939 if (subreq == NULL) {
2940 reply.status = ENOMEM;
2943 tevent_req_set_callback(subreq, set_ban_state_callback, node);
2945 DEBUG(DEBUG_INFO, ("Banning this node for %d seconds\n", ban->time));
2946 node->flags |= NODE_FLAGS_BANNED;
2947 ctdb->vnn_map->generation = INVALID_GENERATION;
2951 reply.errmsg = NULL;
2953 client_send_control(req, header, &reply);
2957 reply.errmsg = "Failed to ban node";
2960 static void control_trans3_commit(TALLOC_CTX *mem_ctx,
2961 struct tevent_req *req,
2962 struct ctdb_req_header *header,
2963 struct ctdb_req_control *request)
2965 struct client_state *state = tevent_req_data(
2966 req, struct client_state);
2967 struct ctdbd_context *ctdb = state->ctdb;
2968 struct ctdb_reply_control reply;
2969 struct database *db;
2972 reply.rdata.opcode = request->opcode;
2974 db = database_find(ctdb->db_map, request->rdata.data.recbuf->db_id);
2977 reply.errmsg = "Unknown database";
2978 client_send_control(req, header, &reply);
2983 (CTDB_DB_FLAGS_PERSISTENT|CTDB_DB_FLAGS_REPLICATED))) {
2985 reply.errmsg = "Transactions on volatile database";
2986 client_send_control(req, header, &reply);
2990 ret = ltdb_transaction(db, request->rdata.data.recbuf);
2993 reply.errmsg = "Transaction failed";
2994 client_send_control(req, header, &reply);
2999 reply.errmsg = NULL;
3000 client_send_control(req, header, &reply);
3003 static void control_get_db_seqnum(TALLOC_CTX *mem_ctx,
3004 struct tevent_req *req,
3005 struct ctdb_req_header *header,
3006 struct ctdb_req_control *request)
3008 struct client_state *state = tevent_req_data(
3009 req, struct client_state);
3010 struct ctdbd_context *ctdb = state->ctdb;
3011 struct ctdb_reply_control reply;
3012 struct database *db;
3015 reply.rdata.opcode = request->opcode;
3017 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3019 reply.status = ENOENT;
3020 reply.errmsg = "Database not found";
3024 ret = database_seqnum(db, &seqnum);
3026 reply.rdata.data.seqnum = seqnum;
3028 reply.errmsg = NULL;
3031 reply.errmsg = "Failed to get seqnum";
3035 client_send_control(req, header, &reply);
3038 static void control_db_get_health(TALLOC_CTX *mem_ctx,
3039 struct tevent_req *req,
3040 struct ctdb_req_header *header,
3041 struct ctdb_req_control *request)
3043 struct client_state *state = tevent_req_data(
3044 req, struct client_state);
3045 struct ctdbd_context *ctdb = state->ctdb;
3046 struct ctdb_reply_control reply;
3047 struct database *db;
3049 reply.rdata.opcode = request->opcode;
3051 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3053 reply.status = ENOENT;
3054 reply.errmsg = "Database not found";
3056 reply.rdata.data.reason = NULL;
3058 reply.errmsg = NULL;
3061 client_send_control(req, header, &reply);
3064 static struct ctdb_iface_list *get_ctdb_iface_list(TALLOC_CTX *mem_ctx,
3065 struct ctdbd_context *ctdb)
3067 struct ctdb_iface_list *iface_list;
3068 struct interface *iface;
3071 iface_list = talloc_zero(mem_ctx, struct ctdb_iface_list);
3072 if (iface_list == NULL) {
3076 iface_list->num = ctdb->iface_map->num;
3077 iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
3079 if (iface_list->iface == NULL) {
3080 TALLOC_FREE(iface_list);
3084 for (i=0; i<iface_list->num; i++) {
3085 iface = &ctdb->iface_map->iface[i];
3086 iface_list->iface[i] = (struct ctdb_iface) {
3087 .link_state = iface->link_up,
3088 .references = iface->references,
3090 strlcpy(iface_list->iface[i].name, iface->name,
3091 sizeof(iface_list->iface[i].name));
3098 static void control_get_public_ip_info(TALLOC_CTX *mem_ctx,
3099 struct tevent_req *req,
3100 struct ctdb_req_header *header,
3101 struct ctdb_req_control *request)
3103 struct client_state *state = tevent_req_data(
3104 req, struct client_state);
3105 struct ctdbd_context *ctdb = state->ctdb;
3106 struct ctdb_reply_control reply;
3107 ctdb_sock_addr *addr = request->rdata.data.addr;
3108 struct ctdb_public_ip_list *known = NULL;
3109 struct ctdb_public_ip_info *info = NULL;
3112 reply.rdata.opcode = request->opcode;
3114 info = talloc_zero(mem_ctx, struct ctdb_public_ip_info);
3116 reply.status = ENOMEM;
3117 reply.errmsg = "Memory error";
3121 reply.rdata.data.ipinfo = info;
3123 if (ctdb->known_ips != NULL) {
3124 known = &ctdb->known_ips[header->destnode];
3126 /* No IPs defined so create a dummy empty struct and
3127 * fall through. The given IP won't be matched
3130 known = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
3131 if (known == NULL) {
3132 reply.status = ENOMEM;
3133 reply.errmsg = "Memory error";
3138 for (i = 0; i < known->num; i++) {
3139 if (ctdb_sock_addr_same_ip(&known->ip[i].addr,
3145 if (i == known->num) {
3146 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
3147 ctdb_sock_addr_to_string(mem_ctx, addr, false));
3149 reply.errmsg = "Unknown address";
3153 info->ip = known->ip[i];
3155 /* The fake PUBLICIPS stanza and resulting known_ips data
3156 * don't know anything about interfaces, so completely fake
3159 info->active_idx = 0;
3161 info->ifaces = get_ctdb_iface_list(mem_ctx, ctdb);
3162 if (info->ifaces == NULL) {
3163 reply.status = ENOMEM;
3164 reply.errmsg = "Memory error";
3169 reply.errmsg = NULL;
3172 client_send_control(req, header, &reply);
3175 static void control_get_ifaces(TALLOC_CTX *mem_ctx,
3176 struct tevent_req *req,
3177 struct ctdb_req_header *header,
3178 struct ctdb_req_control *request)
3180 struct client_state *state = tevent_req_data(
3181 req, struct client_state);
3182 struct ctdbd_context *ctdb = state->ctdb;
3183 struct ctdb_reply_control reply;
3184 struct ctdb_iface_list *iface_list;
3186 reply.rdata.opcode = request->opcode;
3188 iface_list = get_ctdb_iface_list(mem_ctx, ctdb);
3189 if (iface_list == NULL) {
3193 reply.rdata.data.iface_list = iface_list;
3195 reply.errmsg = NULL;
3196 client_send_control(req, header, &reply);
3201 reply.errmsg = "Memory error";
3202 client_send_control(req, header, &reply);
3205 static void control_set_iface_link_state(TALLOC_CTX *mem_ctx,
3206 struct tevent_req *req,
3207 struct ctdb_req_header *header,
3208 struct ctdb_req_control *request)
3210 struct client_state *state = tevent_req_data(
3211 req, struct client_state);
3212 struct ctdbd_context *ctdb = state->ctdb;
3213 struct ctdb_reply_control reply;
3214 struct ctdb_iface *in_iface;
3215 struct interface *iface = NULL;
3216 bool link_up = false;
3219 reply.rdata.opcode = request->opcode;
3221 in_iface = request->rdata.data.iface;
3223 if (in_iface->name[CTDB_IFACE_SIZE] != '\0') {
3224 reply.errmsg = "interface name not terminated";
3228 switch (in_iface->link_state) {
3238 reply.errmsg = "invalid link state";
3242 if (in_iface->references != 0) {
3243 reply.errmsg = "references should be 0";
3247 for (i=0; i<ctdb->iface_map->num; i++) {
3248 if (strcmp(ctdb->iface_map->iface[i].name,
3249 in_iface->name) == 0) {
3250 iface = &ctdb->iface_map->iface[i];
3255 if (iface == NULL) {
3256 reply.errmsg = "interface not found";
3260 iface->link_up = link_up;
3263 reply.errmsg = NULL;
3264 client_send_control(req, header, &reply);
3269 client_send_control(req, header, &reply);
3272 static void control_set_db_readonly(TALLOC_CTX *mem_ctx,
3273 struct tevent_req *req,
3274 struct ctdb_req_header *header,
3275 struct ctdb_req_control *request)
3277 struct client_state *state = tevent_req_data(
3278 req, struct client_state);
3279 struct ctdbd_context *ctdb = state->ctdb;
3280 struct ctdb_reply_control reply;
3281 struct database *db;
3283 reply.rdata.opcode = request->opcode;
3285 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3287 reply.status = ENOENT;
3288 reply.errmsg = "Database not found";
3292 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3293 reply.status = EINVAL;
3294 reply.errmsg = "Can not set READONLY on persistent db";
3298 db->flags |= CTDB_DB_FLAGS_READONLY;
3300 reply.errmsg = NULL;
3303 client_send_control(req, header, &reply);
3306 struct traverse_start_ext_state {
3307 struct tevent_req *req;
3308 struct ctdb_req_header *header;
3311 bool withemptyrecords;
3315 static int traverse_start_ext_handler(struct tdb_context *tdb,
3316 TDB_DATA key, TDB_DATA data,
3319 struct traverse_start_ext_state *state =
3320 (struct traverse_start_ext_state *)private_data;
3321 struct ctdb_rec_data rec;
3322 struct ctdb_req_message_data message;
3325 if (data.dsize < sizeof(struct ctdb_ltdb_header)) {
3329 if ((data.dsize == sizeof(struct ctdb_ltdb_header)) &&
3330 (!state->withemptyrecords)) {
3334 rec = (struct ctdb_rec_data) {
3335 .reqid = state->reqid,
3341 message.srvid = state->srvid;
3342 message.data.dsize = ctdb_rec_data_len(&rec);
3343 message.data.dptr = talloc_size(state->req, message.data.dsize);
3344 if (message.data.dptr == NULL) {
3345 state->status = ENOMEM;
3349 ctdb_rec_data_push(&rec, message.data.dptr, &np);
3350 client_send_message(state->req, state->header, &message);
3352 talloc_free(message.data.dptr);
3357 static void control_traverse_start_ext(TALLOC_CTX *mem_ctx,
3358 struct tevent_req *req,
3359 struct ctdb_req_header *header,
3360 struct ctdb_req_control *request)
3362 struct client_state *state = tevent_req_data(
3363 req, struct client_state);
3364 struct ctdbd_context *ctdb = state->ctdb;
3365 struct ctdb_reply_control reply;
3366 struct database *db;
3367 struct ctdb_traverse_start_ext *ext;
3368 struct traverse_start_ext_state t_state;
3369 struct ctdb_rec_data rec;
3370 struct ctdb_req_message_data message;
3375 reply.rdata.opcode = request->opcode;
3377 ext = request->rdata.data.traverse_start_ext;
3379 db = database_find(ctdb->db_map, ext->db_id);
3382 reply.errmsg = "Unknown database";
3383 client_send_control(req, header, &reply);
3387 t_state = (struct traverse_start_ext_state) {
3390 .reqid = ext->reqid,
3391 .srvid = ext->srvid,
3392 .withemptyrecords = ext->withemptyrecords,
3395 ret = tdb_traverse_read(db->tdb, traverse_start_ext_handler, &t_state);
3396 DEBUG(DEBUG_INFO, ("traversed %d records\n", ret));
3397 if (t_state.status != 0) {
3399 reply.errmsg = "Memory error";
3400 client_send_control(req, header, &reply);
3404 client_send_control(req, header, &reply);
3406 rec = (struct ctdb_rec_data) {
3407 .reqid = ext->reqid,
3413 message.srvid = ext->srvid;
3414 message.data.dsize = ctdb_rec_data_len(&rec);
3415 ctdb_rec_data_push(&rec, buffer, &np);
3416 message.data.dptr = buffer;
3417 client_send_message(req, header, &message);
3420 static void control_set_db_sticky(TALLOC_CTX *mem_ctx,
3421 struct tevent_req *req,
3422 struct ctdb_req_header *header,
3423 struct ctdb_req_control *request)
3425 struct client_state *state = tevent_req_data(
3426 req, struct client_state);
3427 struct ctdbd_context *ctdb = state->ctdb;
3428 struct ctdb_reply_control reply;
3429 struct database *db;
3431 reply.rdata.opcode = request->opcode;
3433 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3435 reply.status = ENOENT;
3436 reply.errmsg = "Database not found";
3440 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3441 reply.status = EINVAL;
3442 reply.errmsg = "Can not set STICKY on persistent db";
3446 db->flags |= CTDB_DB_FLAGS_STICKY;
3448 reply.errmsg = NULL;
3451 client_send_control(req, header, &reply);
3454 static void control_start_ipreallocate(TALLOC_CTX *mem_ctx,
3455 struct tevent_req *req,
3456 struct ctdb_req_header *header,
3457 struct ctdb_req_control *request)
3459 struct ctdb_reply_control reply;
3461 /* Always succeed */
3462 reply.rdata.opcode = request->opcode;
3464 reply.errmsg = NULL;
3466 client_send_control(req, header, &reply);
3469 static void control_ipreallocated(TALLOC_CTX *mem_ctx,
3470 struct tevent_req *req,
3471 struct ctdb_req_header *header,
3472 struct ctdb_req_control *request)
3474 struct ctdb_reply_control reply;
3476 /* Always succeed */
3477 reply.rdata.opcode = request->opcode;
3479 reply.errmsg = NULL;
3481 client_send_control(req, header, &reply);
3484 static void control_get_runstate(TALLOC_CTX *mem_ctx,
3485 struct tevent_req *req,
3486 struct ctdb_req_header *header,
3487 struct ctdb_req_control *request)
3489 struct client_state *state = tevent_req_data(
3490 req, struct client_state);
3491 struct ctdbd_context *ctdb = state->ctdb;
3492 struct ctdb_reply_control reply;
3494 reply.rdata.opcode = request->opcode;
3495 reply.rdata.data.runstate = ctdb->runstate;
3497 reply.errmsg = NULL;
3499 client_send_control(req, header, &reply);
3502 static void control_get_nodes_file(TALLOC_CTX *mem_ctx,
3503 struct tevent_req *req,
3504 struct ctdb_req_header *header,
3505 struct ctdb_req_control *request)
3507 struct ctdb_reply_control reply;
3508 struct ctdb_node_map *nodemap;
3510 reply.rdata.opcode = request->opcode;
3512 nodemap = read_nodes_file(mem_ctx, header->destnode);
3513 if (nodemap == NULL) {
3517 reply.rdata.data.nodemap = nodemap;
3519 reply.errmsg = NULL;
3520 client_send_control(req, header, &reply);
3525 reply.errmsg = "Failed to read nodes file";
3526 client_send_control(req, header, &reply);
3529 static void control_db_open_flags(TALLOC_CTX *mem_ctx,
3530 struct tevent_req *req,
3531 struct ctdb_req_header *header,
3532 struct ctdb_req_control *request)
3534 struct client_state *state = tevent_req_data(
3535 req, struct client_state);
3536 struct ctdbd_context *ctdb = state->ctdb;
3537 struct ctdb_reply_control reply;
3538 struct database *db;
3540 reply.rdata.opcode = request->opcode;
3542 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3544 reply.status = ENOENT;
3545 reply.errmsg = "Database not found";
3547 reply.rdata.data.tdb_flags = database_flags(db->flags);
3549 reply.errmsg = NULL;
3552 client_send_control(req, header, &reply);
3555 static void control_db_attach_replicated(TALLOC_CTX *mem_ctx,
3556 struct tevent_req *req,
3557 struct ctdb_req_header *header,
3558 struct ctdb_req_control *request)
3560 struct client_state *state = tevent_req_data(
3561 req, struct client_state);
3562 struct ctdbd_context *ctdb = state->ctdb;
3563 struct ctdb_reply_control reply;
3564 struct database *db;
3566 reply.rdata.opcode = request->opcode;
3568 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
3569 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
3574 db = database_new(ctdb->db_map, request->rdata.data.db_name,
3575 CTDB_DB_FLAGS_REPLICATED);
3578 reply.errmsg = "Failed to attach database";
3579 client_send_control(req, header, &reply);
3584 reply.rdata.data.db_id = db->id;
3586 reply.errmsg = NULL;
3587 client_send_control(req, header, &reply);
3590 static void control_check_pid_srvid(TALLOC_CTX *mem_ctx,
3591 struct tevent_req *req,
3592 struct ctdb_req_header *header,
3593 struct ctdb_req_control *request)
3595 struct client_state *state = tevent_req_data(
3596 req, struct client_state);
3597 struct ctdbd_context *ctdb = state->ctdb;
3598 struct ctdb_client *client;
3599 struct client_state *cstate;
3600 struct ctdb_reply_control reply;
3601 bool pid_found, srvid_found;
3604 reply.rdata.opcode = request->opcode;
3607 srvid_found = false;
3609 for (client=ctdb->client_list; client != NULL; client=client->next) {
3610 if (client->pid == request->rdata.data.pid_srvid->pid) {
3612 cstate = (struct client_state *)client->state;
3613 ret = srvid_exists(ctdb->srv,
3614 request->rdata.data.pid_srvid->srvid,
3618 ret = kill(cstate->pid, 0);
3621 reply.errmsg = strerror(errno);
3624 reply.errmsg = NULL;
3632 reply.errmsg = "No client for PID";
3633 } else if (! srvid_found) {
3635 reply.errmsg = "No client for PID and SRVID";
3638 client_send_control(req, header, &reply);
3641 static void control_disable_node(TALLOC_CTX *mem_ctx,
3642 struct tevent_req *req,
3643 struct ctdb_req_header *header,
3644 struct ctdb_req_control *request)
3646 struct client_state *state = tevent_req_data(
3647 req, struct client_state);
3648 struct ctdbd_context *ctdb = state->ctdb;
3649 struct ctdb_reply_control reply;
3651 reply.rdata.opcode = request->opcode;
3653 DEBUG(DEBUG_INFO, ("Disabling node\n"));
3654 ctdb->node_map->node[header->destnode].flags |=
3655 NODE_FLAGS_PERMANENTLY_DISABLED;
3658 reply.errmsg = NULL;
3660 client_send_control(req, header, &reply);
3664 static void control_enable_node(TALLOC_CTX *mem_ctx,
3665 struct tevent_req *req,
3666 struct ctdb_req_header *header,
3667 struct ctdb_req_control *request)
3669 struct client_state *state = tevent_req_data(
3670 req, struct client_state);
3671 struct ctdbd_context *ctdb = state->ctdb;
3672 struct ctdb_reply_control reply;
3674 reply.rdata.opcode = request->opcode;
3676 DEBUG(DEBUG_INFO, ("Enable node\n"));
3677 ctdb->node_map->node[header->destnode].flags &=
3678 ~NODE_FLAGS_PERMANENTLY_DISABLED;
3681 reply.errmsg = NULL;
3683 client_send_control(req, header, &reply);
3687 static bool fake_control_failure(TALLOC_CTX *mem_ctx,
3688 struct tevent_req *req,
3689 struct ctdb_req_header *header,
3690 struct ctdb_req_control *request)
3692 struct client_state *state = tevent_req_data(
3693 req, struct client_state);
3694 struct ctdbd_context *ctdb = state->ctdb;
3695 struct ctdb_reply_control reply;
3696 struct fake_control_failure *f = NULL;
3698 D_DEBUG("Checking fake control failure for control %u on node %u\n",
3699 request->opcode, header->destnode);
3700 for (f = ctdb->control_failures; f != NULL; f = f->next) {
3701 if (f->opcode == request->opcode &&
3702 (f->pnn == header->destnode ||
3703 f->pnn == CTDB_UNKNOWN_PNN)) {
3705 reply.rdata.opcode = request->opcode;
3706 if (strcmp(f->error, "TIMEOUT") == 0) {
3707 /* Causes no reply */
3708 D_ERR("Control %u fake timeout on node %u\n",
3709 request->opcode, header->destnode);
3711 } else if (strcmp(f->error, "ERROR") == 0) {
3712 D_ERR("Control %u fake error on node %u\n",
3713 request->opcode, header->destnode);
3715 reply.errmsg = f->comment;
3716 client_send_control(req, header, &reply);
3725 static void control_error(TALLOC_CTX *mem_ctx,
3726 struct tevent_req *req,
3727 struct ctdb_req_header *header,
3728 struct ctdb_req_control *request)
3730 struct ctdb_reply_control reply;
3732 D_DEBUG("Control %u not implemented\n", request->opcode);
3734 reply.rdata.opcode = request->opcode;
3736 reply.errmsg = "Not implemented";
3738 client_send_control(req, header, &reply);
3742 * Handling protocol - messages
3745 struct disable_recoveries_state {
3749 static void disable_recoveries_callback(struct tevent_req *subreq)
3751 struct disable_recoveries_state *substate = tevent_req_callback_data(
3752 subreq, struct disable_recoveries_state);
3755 status = tevent_wakeup_recv(subreq);
3756 TALLOC_FREE(subreq);
3758 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
3761 substate->node->recovery_disabled = false;
3762 TALLOC_FREE(substate->node->recovery_substate);
3765 static void message_disable_recoveries(TALLOC_CTX *mem_ctx,
3766 struct tevent_req *req,
3767 struct ctdb_req_header *header,
3768 struct ctdb_req_message *request)
3770 struct client_state *state = tevent_req_data(
3771 req, struct client_state);
3772 struct tevent_req *subreq;
3773 struct ctdbd_context *ctdb = state->ctdb;
3774 struct disable_recoveries_state *substate;
3775 struct ctdb_disable_message *disable = request->data.disable;
3776 struct ctdb_req_message_data reply;
3781 node = &ctdb->node_map->node[header->destnode];
3783 if (disable->timeout == 0) {
3784 TALLOC_FREE(node->recovery_substate);
3785 node->recovery_disabled = false;
3786 DEBUG(DEBUG_INFO, ("Enabled recoveries on node %u\n",
3791 substate = talloc_zero(ctdb->node_map,
3792 struct disable_recoveries_state);
3793 if (substate == NULL) {
3797 substate->node = node;
3799 subreq = tevent_wakeup_send(substate, state->ev,
3800 tevent_timeval_current_ofs(
3801 disable->timeout, 0));
3802 if (subreq == NULL) {
3803 talloc_free(substate);
3806 tevent_req_set_callback(subreq, disable_recoveries_callback, substate);
3808 DEBUG(DEBUG_INFO, ("Disabled recoveries for %d seconds on node %u\n",
3809 disable->timeout, header->destnode));
3810 node->recovery_substate = substate;
3811 node->recovery_disabled = true;
3814 ret = header->destnode;
3817 reply.srvid = disable->srvid;
3818 data.dptr = (uint8_t *)&ret;
3819 data.dsize = sizeof(int);
3822 client_send_message(req, header, &reply);
3825 static void message_takeover_run(TALLOC_CTX *mem_ctx,
3826 struct tevent_req *req,
3827 struct ctdb_req_header *header,
3828 struct ctdb_req_message *request)
3830 struct client_state *state = tevent_req_data(
3831 req, struct client_state);
3832 struct ctdbd_context *ctdb = state->ctdb;
3833 struct ctdb_srvid_message *srvid = request->data.msg;
3834 struct ctdb_req_message_data reply;
3838 if (header->destnode != ctdb->node_map->recmaster) {
3839 /* No reply! Only recmaster replies... */
3843 DEBUG(DEBUG_INFO, ("IP takover run on node %u\n",
3845 ret = header->destnode;
3847 reply.srvid = srvid->srvid;
3848 data.dptr = (uint8_t *)&ret;
3849 data.dsize = sizeof(int);
3852 client_send_message(req, header, &reply);
3856 * Handle a single client
3859 static void client_read_handler(uint8_t *buf, size_t buflen,
3860 void *private_data);
3861 static void client_dead_handler(void *private_data);
3862 static void client_process_packet(struct tevent_req *req,
3863 uint8_t *buf, size_t buflen);
3864 static void client_process_call(struct tevent_req *req,
3865 uint8_t *buf, size_t buflen);
3866 static void client_process_message(struct tevent_req *req,
3867 uint8_t *buf, size_t buflen);
3868 static void client_process_control(struct tevent_req *req,
3869 uint8_t *buf, size_t buflen);
3870 static void client_reply_done(struct tevent_req *subreq);
3872 static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
3873 struct tevent_context *ev,
3874 int fd, struct ctdbd_context *ctdb,
3877 struct tevent_req *req;
3878 struct client_state *state;
3881 req = tevent_req_create(mem_ctx, &state, struct client_state);
3891 (void) ctdb_get_peer_pid(fd, &state->pid);
3893 ret = comm_setup(state, ev, fd, client_read_handler, req,
3894 client_dead_handler, req, &state->comm);
3896 tevent_req_error(req, ret);
3897 return tevent_req_post(req, ev);
3900 ret = client_add(ctdb, state->pid, state);
3902 tevent_req_error(req, ret);
3903 return tevent_req_post(req, ev);
3906 DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
3911 static void client_read_handler(uint8_t *buf, size_t buflen,
3914 struct tevent_req *req = talloc_get_type_abort(
3915 private_data, struct tevent_req);
3916 struct client_state *state = tevent_req_data(
3917 req, struct client_state);
3918 struct ctdbd_context *ctdb = state->ctdb;
3919 struct ctdb_req_header header;
3924 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3929 if (buflen != header.length) {
3933 ret = ctdb_req_header_verify(&header, 0);
3938 header_fix_pnn(&header, ctdb);
3940 if (header.destnode == CTDB_BROADCAST_ALL) {
3941 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3942 header.destnode = i;
3944 ctdb_req_header_push(&header, buf, &np);
3945 client_process_packet(req, buf, buflen);
3950 if (header.destnode == CTDB_BROADCAST_CONNECTED) {
3951 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3952 if (ctdb->node_map->node[i].flags &
3953 NODE_FLAGS_DISCONNECTED) {
3957 header.destnode = i;
3959 ctdb_req_header_push(&header, buf, &np);
3960 client_process_packet(req, buf, buflen);
3965 if (header.destnode > ctdb->node_map->num_nodes) {
3966 fprintf(stderr, "Invalid destination pnn 0x%x\n",
3972 if (ctdb->node_map->node[header.destnode].flags & NODE_FLAGS_DISCONNECTED) {
3973 fprintf(stderr, "Packet for disconnected node pnn %u\n",
3978 ctdb_req_header_push(&header, buf, &np);
3979 client_process_packet(req, buf, buflen);
3982 static void client_dead_handler(void *private_data)
3984 struct tevent_req *req = talloc_get_type_abort(
3985 private_data, struct tevent_req);
3987 tevent_req_done(req);
3990 static void client_process_packet(struct tevent_req *req,
3991 uint8_t *buf, size_t buflen)
3993 struct ctdb_req_header header;
3997 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
4002 switch (header.operation) {
4004 client_process_call(req, buf, buflen);
4007 case CTDB_REQ_MESSAGE:
4008 client_process_message(req, buf, buflen);
4011 case CTDB_REQ_CONTROL:
4012 client_process_control(req, buf, buflen);
4020 static void client_process_call(struct tevent_req *req,
4021 uint8_t *buf, size_t buflen)
4023 struct client_state *state = tevent_req_data(
4024 req, struct client_state);
4025 struct ctdbd_context *ctdb = state->ctdb;
4026 TALLOC_CTX *mem_ctx;
4027 struct ctdb_req_header header;
4028 struct ctdb_req_call request;
4029 struct ctdb_reply_call reply;
4030 struct database *db;
4031 struct ctdb_ltdb_header hdr;
4035 mem_ctx = talloc_new(state);
4036 if (tevent_req_nomem(mem_ctx, req)) {
4040 ret = ctdb_req_call_pull(buf, buflen, &header, mem_ctx, &request);
4042 talloc_free(mem_ctx);
4043 tevent_req_error(req, ret);
4047 header_fix_pnn(&header, ctdb);
4049 if (header.destnode >= ctdb->node_map->num_nodes) {
4053 DEBUG(DEBUG_INFO, ("call db_id = %u\n", request.db_id));
4055 db = database_find(ctdb->db_map, request.db_id);
4060 ret = ltdb_fetch(db, request.key, &hdr, mem_ctx, &data);
4065 /* Fake migration */
4066 if (hdr.dmaster != ctdb->node_map->pnn) {
4067 hdr.dmaster = ctdb->node_map->pnn;
4069 ret = ltdb_store(db, request.key, &hdr, data);
4075 talloc_free(mem_ctx);
4078 reply.data = tdb_null;
4080 client_send_call(req, &header, &reply);
4084 talloc_free(mem_ctx);
4086 reply.data = tdb_null;
4088 client_send_call(req, &header, &reply);
4091 static void client_process_message(struct tevent_req *req,
4092 uint8_t *buf, size_t buflen)
4094 struct client_state *state = tevent_req_data(
4095 req, struct client_state);
4096 struct ctdbd_context *ctdb = state->ctdb;
4097 TALLOC_CTX *mem_ctx;
4098 struct ctdb_req_header header;
4099 struct ctdb_req_message request;
4103 mem_ctx = talloc_new(state);
4104 if (tevent_req_nomem(mem_ctx, req)) {
4108 ret = ctdb_req_message_pull(buf, buflen, &header, mem_ctx, &request);
4110 talloc_free(mem_ctx);
4111 tevent_req_error(req, ret);
4115 header_fix_pnn(&header, ctdb);
4117 if (header.destnode >= ctdb->node_map->num_nodes) {
4118 /* Many messages are not replied to, so just behave as
4119 * though this message was not received */
4120 fprintf(stderr, "Invalid node %d\n", header.destnode);
4121 talloc_free(mem_ctx);
4125 srvid = request.srvid;
4126 DEBUG(DEBUG_INFO, ("request srvid = 0x%"PRIx64"\n", srvid));
4128 if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
4129 message_disable_recoveries(mem_ctx, req, &header, &request);
4130 } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
4131 message_takeover_run(mem_ctx, req, &header, &request);
4133 D_DEBUG("Message id 0x%"PRIx64" not implemented\n", srvid);
4137 talloc_free(mem_ctx);
4140 static void client_process_control(struct tevent_req *req,
4141 uint8_t *buf, size_t buflen)
4143 struct client_state *state = tevent_req_data(
4144 req, struct client_state);
4145 struct ctdbd_context *ctdb = state->ctdb;
4146 TALLOC_CTX *mem_ctx;
4147 struct ctdb_req_header header;
4148 struct ctdb_req_control request;
4151 mem_ctx = talloc_new(state);
4152 if (tevent_req_nomem(mem_ctx, req)) {
4156 ret = ctdb_req_control_pull(buf, buflen, &header, mem_ctx, &request);
4158 talloc_free(mem_ctx);
4159 tevent_req_error(req, ret);
4163 header_fix_pnn(&header, ctdb);
4165 if (header.destnode >= ctdb->node_map->num_nodes) {
4166 struct ctdb_reply_control reply;
4168 reply.rdata.opcode = request.opcode;
4169 reply.errmsg = "Invalid node";
4171 client_send_control(req, &header, &reply);
4175 DEBUG(DEBUG_INFO, ("request opcode = %u, reqid = %u\n",
4176 request.opcode, header.reqid));
4178 if (fake_control_failure(mem_ctx, req, &header, &request)) {
4182 switch (request.opcode) {
4183 case CTDB_CONTROL_PROCESS_EXISTS:
4184 control_process_exists(mem_ctx, req, &header, &request);
4187 case CTDB_CONTROL_PING:
4188 control_ping(mem_ctx, req, &header, &request);
4191 case CTDB_CONTROL_GETDBPATH:
4192 control_getdbpath(mem_ctx, req, &header, &request);
4195 case CTDB_CONTROL_GETVNNMAP:
4196 control_getvnnmap(mem_ctx, req, &header, &request);
4199 case CTDB_CONTROL_GET_DEBUG:
4200 control_get_debug(mem_ctx, req, &header, &request);
4203 case CTDB_CONTROL_SET_DEBUG:
4204 control_set_debug(mem_ctx, req, &header, &request);
4207 case CTDB_CONTROL_GET_DBMAP:
4208 control_get_dbmap(mem_ctx, req, &header, &request);
4211 case CTDB_CONTROL_GET_RECMODE:
4212 control_get_recmode(mem_ctx, req, &header, &request);
4215 case CTDB_CONTROL_SET_RECMODE:
4216 control_set_recmode(mem_ctx, req, &header, &request);
4219 case CTDB_CONTROL_DB_ATTACH:
4220 control_db_attach(mem_ctx, req, &header, &request);
4223 case CTDB_CONTROL_REGISTER_SRVID:
4224 control_register_srvid(mem_ctx, req, &header, &request);
4227 case CTDB_CONTROL_DEREGISTER_SRVID:
4228 control_deregister_srvid(mem_ctx, req, &header, &request);
4231 case CTDB_CONTROL_GET_DBNAME:
4232 control_get_dbname(mem_ctx, req, &header, &request);
4235 case CTDB_CONTROL_GET_PID:
4236 control_get_pid(mem_ctx, req, &header, &request);
4239 case CTDB_CONTROL_GET_PNN:
4240 control_get_pnn(mem_ctx, req, &header, &request);
4243 case CTDB_CONTROL_SHUTDOWN:
4244 control_shutdown(mem_ctx, req, &header, &request);
4247 case CTDB_CONTROL_SET_TUNABLE:
4248 control_set_tunable(mem_ctx, req, &header, &request);
4251 case CTDB_CONTROL_GET_TUNABLE:
4252 control_get_tunable(mem_ctx, req, &header, &request);
4255 case CTDB_CONTROL_LIST_TUNABLES:
4256 control_list_tunables(mem_ctx, req, &header, &request);
4259 case CTDB_CONTROL_MODIFY_FLAGS:
4260 control_modify_flags(mem_ctx, req, &header, &request);
4263 case CTDB_CONTROL_GET_ALL_TUNABLES:
4264 control_get_all_tunables(mem_ctx, req, &header, &request);
4267 case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
4268 control_db_attach_persistent(mem_ctx, req, &header, &request);
4271 case CTDB_CONTROL_UPTIME:
4272 control_uptime(mem_ctx, req, &header, &request);
4275 case CTDB_CONTROL_RELOAD_NODES_FILE:
4276 control_reload_nodes_file(mem_ctx, req, &header, &request);
4279 case CTDB_CONTROL_GET_CAPABILITIES:
4280 control_get_capabilities(mem_ctx, req, &header, &request);
4283 case CTDB_CONTROL_RELEASE_IP:
4284 control_release_ip(mem_ctx, req, &header, &request);
4287 case CTDB_CONTROL_TAKEOVER_IP:
4288 control_takeover_ip(mem_ctx, req, &header, &request);
4291 case CTDB_CONTROL_GET_PUBLIC_IPS:
4292 control_get_public_ips(mem_ctx, req, &header, &request);
4295 case CTDB_CONTROL_GET_NODEMAP:
4296 control_get_nodemap(mem_ctx, req, &header, &request);
4299 case CTDB_CONTROL_GET_RECLOCK_FILE:
4300 control_get_reclock_file(mem_ctx, req, &header, &request);
4303 case CTDB_CONTROL_STOP_NODE:
4304 control_stop_node(mem_ctx, req, &header, &request);
4307 case CTDB_CONTROL_CONTINUE_NODE:
4308 control_continue_node(mem_ctx, req, &header, &request);
4311 case CTDB_CONTROL_SET_BAN_STATE:
4312 control_set_ban_state(mem_ctx, req, &header, &request);
4315 case CTDB_CONTROL_TRANS3_COMMIT:
4316 control_trans3_commit(mem_ctx, req, &header, &request);
4319 case CTDB_CONTROL_GET_DB_SEQNUM:
4320 control_get_db_seqnum(mem_ctx, req, &header, &request);
4323 case CTDB_CONTROL_DB_GET_HEALTH:
4324 control_db_get_health(mem_ctx, req, &header, &request);
4327 case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
4328 control_get_public_ip_info(mem_ctx, req, &header, &request);
4331 case CTDB_CONTROL_GET_IFACES:
4332 control_get_ifaces(mem_ctx, req, &header, &request);
4335 case CTDB_CONTROL_SET_IFACE_LINK_STATE:
4336 control_set_iface_link_state(mem_ctx, req, &header, &request);
4339 case CTDB_CONTROL_SET_DB_READONLY:
4340 control_set_db_readonly(mem_ctx, req, &header, &request);
4343 case CTDB_CONTROL_TRAVERSE_START_EXT:
4344 control_traverse_start_ext(mem_ctx, req, &header, &request);
4347 case CTDB_CONTROL_SET_DB_STICKY:
4348 control_set_db_sticky(mem_ctx, req, &header, &request);
4351 case CTDB_CONTROL_IPREALLOCATED:
4352 control_ipreallocated(mem_ctx, req, &header, &request);
4355 case CTDB_CONTROL_GET_RUNSTATE:
4356 control_get_runstate(mem_ctx, req, &header, &request);
4359 case CTDB_CONTROL_GET_NODES_FILE:
4360 control_get_nodes_file(mem_ctx, req, &header, &request);
4363 case CTDB_CONTROL_DB_OPEN_FLAGS:
4364 control_db_open_flags(mem_ctx, req, &header, &request);
4367 case CTDB_CONTROL_DB_ATTACH_REPLICATED:
4368 control_db_attach_replicated(mem_ctx, req, &header, &request);
4371 case CTDB_CONTROL_CHECK_PID_SRVID:
4372 control_check_pid_srvid(mem_ctx, req, &header, &request);
4375 case CTDB_CONTROL_DISABLE_NODE:
4376 control_disable_node(mem_ctx, req, &header, &request);
4379 case CTDB_CONTROL_ENABLE_NODE:
4380 control_enable_node(mem_ctx, req, &header, &request);
4383 case CTDB_CONTROL_START_IPREALLOCATE:
4384 control_start_ipreallocate(mem_ctx, req, &header, &request);
4388 if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) {
4389 control_error(mem_ctx, req, &header, &request);
4395 talloc_free(mem_ctx);
4398 static int client_recv(struct tevent_req *req, int *perr)
4400 struct client_state *state = tevent_req_data(
4401 req, struct client_state);
4404 DEBUG(DEBUG_INFO, ("Client done fd=%d\n", state->fd));
4407 if (tevent_req_is_unix_error(req, &err)) {
4414 return state->status;
4421 struct server_state {
4422 struct tevent_context *ev;
4423 struct ctdbd_context *ctdb;
4424 struct tevent_timer *leader_broadcast_te;
4428 static void server_leader_broadcast(struct tevent_context *ev,
4429 struct tevent_timer *te,
4430 struct timeval current_time,
4431 void *private_data);
4432 static void server_new_client(struct tevent_req *subreq);
4433 static void server_client_done(struct tevent_req *subreq);
4435 static struct tevent_req *server_send(TALLOC_CTX *mem_ctx,
4436 struct tevent_context *ev,
4437 struct ctdbd_context *ctdb,
4440 struct tevent_req *req, *subreq;
4441 struct server_state *state;
4443 req = tevent_req_create(mem_ctx, &state, struct server_state);
4452 state->leader_broadcast_te = tevent_add_timer(state->ev,
4454 timeval_current_ofs(0, 0),
4455 server_leader_broadcast,
4457 if (state->leader_broadcast_te == NULL) {
4458 DBG_WARNING("Failed to set up leader broadcast\n");
4461 subreq = accept_send(state, ev, fd);
4462 if (tevent_req_nomem(subreq, req)) {
4463 return tevent_req_post(req, ev);
4465 tevent_req_set_callback(subreq, server_new_client, req);
4470 static void server_leader_broadcast(struct tevent_context *ev,
4471 struct tevent_timer *te,
4472 struct timeval current_time,
4475 struct server_state *state = talloc_get_type_abort(
4476 private_data, struct server_state);
4477 struct ctdbd_context *ctdb = state->ctdb;
4478 uint32_t leader = ctdb->node_map->recmaster;
4482 if (leader == CTDB_UNKNOWN_PNN) {
4486 data.dptr = (uint8_t *)&leader;
4487 data.dsize = sizeof(leader);
4489 ret = srvid_dispatch(ctdb->srv, CTDB_SRVID_LEADER, 0, data);
4491 DBG_WARNING("Failed to send leader broadcast, ret=%d\n", ret);
4495 state->leader_broadcast_te = tevent_add_timer(state->ev,
4497 timeval_current_ofs(1, 0),
4498 server_leader_broadcast,
4500 if (state->leader_broadcast_te == NULL) {
4501 DBG_WARNING("Failed to set up leader broadcast\n");
4505 static void server_new_client(struct tevent_req *subreq)
4507 struct tevent_req *req = tevent_req_callback_data(
4508 subreq, struct tevent_req);
4509 struct server_state *state = tevent_req_data(
4510 req, struct server_state);
4511 struct ctdbd_context *ctdb = state->ctdb;
4515 client_fd = accept_recv(subreq, NULL, NULL, &ret);
4516 TALLOC_FREE(subreq);
4517 if (client_fd == -1) {
4518 tevent_req_error(req, ret);
4522 subreq = client_send(state, state->ev, client_fd,
4523 ctdb, ctdb->node_map->pnn);
4524 if (tevent_req_nomem(subreq, req)) {
4527 tevent_req_set_callback(subreq, server_client_done, req);
4529 ctdb->num_clients += 1;
4531 subreq = accept_send(state, state->ev, state->fd);
4532 if (tevent_req_nomem(subreq, req)) {
4535 tevent_req_set_callback(subreq, server_new_client, req);
4538 static void server_client_done(struct tevent_req *subreq)
4540 struct tevent_req *req = tevent_req_callback_data(
4541 subreq, struct tevent_req);
4542 struct server_state *state = tevent_req_data(
4543 req, struct server_state);
4544 struct ctdbd_context *ctdb = state->ctdb;
4548 status = client_recv(subreq, &ret);
4549 TALLOC_FREE(subreq);
4551 tevent_req_error(req, ret);
4555 ctdb->num_clients -= 1;
4558 /* Special status, to shutdown server */
4559 DEBUG(DEBUG_INFO, ("Shutting down server\n"));
4560 tevent_req_done(req);
4564 static bool server_recv(struct tevent_req *req, int *perr)
4568 if (tevent_req_is_unix_error(req, &err)) {
4581 static int socket_init(const char *sockpath)
4583 struct sockaddr_un addr;
4587 memset(&addr, 0, sizeof(addr));
4588 addr.sun_family = AF_UNIX;
4590 len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
4591 if (len >= sizeof(addr.sun_path)) {
4592 fprintf(stderr, "path too long: %s\n", sockpath);
4596 fd = socket(AF_UNIX, SOCK_STREAM, 0);
4598 fprintf(stderr, "socket failed - %s\n", sockpath);
4602 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
4604 fprintf(stderr, "bind failed - %s\n", sockpath);
4608 ret = listen(fd, 10);
4610 fprintf(stderr, "listen failed\n");
4614 DEBUG(DEBUG_INFO, ("Socket init done\n"));
4625 static struct options {
4627 const char *sockpath;
4628 const char *pidfile;
4629 const char *debuglevel;
4632 static struct poptOption cmdline_options[] = {
4634 { "dbdir", 'D', POPT_ARG_STRING, &options.dbdir, 0,
4635 "Database directory", "directory" },
4636 { "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
4637 "Unix domain socket path", "filename" },
4638 { "pidfile", 'p', POPT_ARG_STRING, &options.pidfile, 0,
4639 "pid file", "filename" } ,
4640 { "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
4641 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
4645 static void cleanup(void)
4647 unlink(options.sockpath);
4648 unlink(options.pidfile);
4651 static void signal_handler(int sig)
4657 static void start_server(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
4658 struct ctdbd_context *ctdb, int fd, int pfd)
4660 struct tevent_req *req;
4665 signal(SIGTERM, signal_handler);
4667 req = server_send(mem_ctx, ev, ctdb, fd);
4669 fprintf(stderr, "Memory error\n");
4673 len = write(pfd, &ret, sizeof(ret));
4674 if (len != sizeof(ret)) {
4675 fprintf(stderr, "Failed to send message to parent\n");
4680 tevent_req_poll(req, ev);
4682 server_recv(req, &ret);
4688 int main(int argc, const char *argv[])
4690 TALLOC_CTX *mem_ctx;
4691 struct ctdbd_context *ctdb;
4692 struct tevent_context *ev;
4694 int opt, fd, ret, pfd[2];
4699 pc = poptGetContext(argv[0], argc, argv, cmdline_options,
4700 POPT_CONTEXT_KEEP_FIRST);
4701 while ((opt = poptGetNextOpt(pc)) != -1) {
4702 fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
4706 if (options.dbdir == NULL) {
4707 fprintf(stderr, "Please specify database directory\n");
4708 poptPrintHelp(pc, stdout, 0);
4712 if (options.sockpath == NULL) {
4713 fprintf(stderr, "Please specify socket path\n");
4714 poptPrintHelp(pc, stdout, 0);
4718 if (options.pidfile == NULL) {
4719 fprintf(stderr, "Please specify pid file\n");
4720 poptPrintHelp(pc, stdout, 0);
4724 mem_ctx = talloc_new(NULL);
4725 if (mem_ctx == NULL) {
4726 fprintf(stderr, "Memory error\n");
4730 ret = logging_init(mem_ctx, "file:", options.debuglevel, "fake-ctdbd");
4732 fprintf(stderr, "Invalid debug level\n");
4733 poptPrintHelp(pc, stdout, 0);
4737 ctdb = ctdbd_setup(mem_ctx, options.dbdir);
4742 if (! ctdbd_verify(ctdb)) {
4746 ev = tevent_context_init(mem_ctx);
4748 fprintf(stderr, "Memory error\n");
4752 fd = socket_init(options.sockpath);
4759 fprintf(stderr, "Failed to create pipe\n");
4766 fprintf(stderr, "Failed to fork\n");
4774 start_server(mem_ctx, ev, ctdb, fd, pfd[1]);
4781 len = read(pfd[0], &ret, sizeof(ret));
4783 if (len != sizeof(ret)) {
4784 fprintf(stderr, "len = %zi\n", len);
4785 fprintf(stderr, "Failed to get message from child\n");
4790 fp = fopen(options.pidfile, "w");
4792 fprintf(stderr, "Failed to open pid file %s\n",
4797 fprintf(fp, "%d\n", pid);