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/async_req/async_sock.h"
36 #include "protocol/protocol.h"
37 #include "protocol/protocol_api.h"
38 #include "protocol/protocol_util.h"
39 #include "protocol/protocol_private.h"
41 #include "common/comm.h"
42 #include "common/logging.h"
43 #include "common/tunable.h"
44 #include "common/srvid.h"
46 #include "ipalloc_read_known_ips.h"
49 #define CTDB_PORT 4379
51 /* A fake flag that is only supported by some functions */
52 #define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
58 uint32_t capabilities;
59 bool recovery_disabled;
60 void *recovery_substate;
76 struct interface_map {
78 struct interface *iface;
89 struct database *prev, *next;
92 struct tdb_context *tdb;
103 struct fake_control_failure {
104 struct fake_control_failure *prev, *next;
105 enum ctdb_controls opcode;
112 struct ctdb_client *prev, *next;
113 struct ctdbd_context *ctdb;
118 struct ctdbd_context {
119 struct node_map *node_map;
120 struct interface_map *iface_map;
121 struct vnn_map *vnn_map;
122 struct database_map *db_map;
123 struct srvid_context *srv;
125 struct timeval start_time;
126 struct timeval recovery_start_time;
127 struct timeval recovery_end_time;
128 bool takeover_disabled;
130 enum ctdb_runstate runstate;
131 struct ctdb_tunable_list tun_list;
133 struct ctdb_public_ip_list *known_ips;
134 struct fake_control_failure *control_failures;
135 struct ctdb_client *client_list;
142 static struct node_map *nodemap_init(TALLOC_CTX *mem_ctx)
144 struct node_map *node_map;
146 node_map = talloc_zero(mem_ctx, struct node_map);
147 if (node_map == NULL) {
151 node_map->pnn = CTDB_UNKNOWN_PNN;
152 node_map->recmaster = CTDB_UNKNOWN_PNN;
157 /* Read a nodemap from stdin. Each line looks like:
158 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
159 * EOF or a blank line terminates input.
161 * By default, capablities for each node are
162 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER. These 2
163 * capabilities can be faked off by adding, for example,
164 * -CTDB_CAP_RECMASTER.
167 static bool nodemap_parse(struct node_map *node_map)
171 while ((fgets(line, sizeof(line), stdin) != NULL)) {
172 uint32_t pnn, flags, capabilities;
175 ctdb_sock_addr saddr;
179 if (line[0] == '\n') {
183 /* Get rid of pesky newline */
184 if ((t = strchr(line, '\n')) != NULL) {
189 tok = strtok(line, " \t");
191 fprintf(stderr, "bad line (%s) - missing PNN\n", line);
194 pnn = (uint32_t)strtoul(tok, NULL, 0);
197 tok = strtok(NULL, " \t");
199 fprintf(stderr, "bad line (%s) - missing IP\n", line);
202 ret = ctdb_sock_addr_from_string(tok, &saddr, false);
204 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
207 ctdb_sock_addr_set_port(&saddr, CTDB_PORT);
208 ip = talloc_strdup(node_map, tok);
214 tok = strtok(NULL, " \t");
216 fprintf(stderr, "bad line (%s) - missing flags\n",
220 flags = (uint32_t)strtoul(tok, NULL, 0);
221 /* Handle deleted nodes */
222 if (flags & NODE_FLAGS_DELETED) {
224 ip = talloc_strdup(node_map, "0.0.0.0");
229 capabilities = CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER;
231 tok = strtok(NULL, " \t");
232 while (tok != NULL) {
233 if (strcmp(tok, "CURRENT") == 0) {
235 } else if (strcmp(tok, "RECMASTER") == 0) {
236 node_map->recmaster = pnn;
237 } else if (strcmp(tok, "-CTDB_CAP_RECMASTER") == 0) {
238 capabilities &= ~CTDB_CAP_RECMASTER;
239 } else if (strcmp(tok, "-CTDB_CAP_LMASTER") == 0) {
240 capabilities &= ~CTDB_CAP_LMASTER;
241 } else if (strcmp(tok, "TIMEOUT") == 0) {
242 /* This can be done with just a flag
243 * value but it is probably clearer
244 * and less error-prone to fake this
245 * with an explicit token */
246 flags |= NODE_FLAGS_FAKE_TIMEOUT;
248 tok = strtok(NULL, " \t");
251 node_map->node = talloc_realloc(node_map, node_map->node,
253 node_map->num_nodes + 1);
254 if (node_map->node == NULL) {
257 node = &node_map->node[node_map->num_nodes];
259 ret = ctdb_sock_addr_from_string(ip, &node->addr, false);
261 fprintf(stderr, "bad line (%s) - invalid IP\n", line);
264 ctdb_sock_addr_set_port(&node->addr, CTDB_PORT);
267 node->capabilities = capabilities;
268 node->recovery_disabled = false;
269 node->recovery_substate = NULL;
271 node_map->num_nodes += 1;
274 DEBUG(DEBUG_INFO, ("Parsing nodemap done\n"));
278 DEBUG(DEBUG_INFO, ("Parsing nodemap failed\n"));
283 /* Append a node to a node map with given address and flags */
284 static bool node_map_add(struct ctdb_node_map *nodemap,
285 const char *nstr, uint32_t flags)
289 struct ctdb_node_and_flags *n;
292 ret = ctdb_sock_addr_from_string(nstr, &addr, false);
294 fprintf(stderr, "Invalid IP address %s\n", nstr);
297 ctdb_sock_addr_set_port(&addr, CTDB_PORT);
300 nodemap->node = talloc_realloc(nodemap, nodemap->node,
301 struct ctdb_node_and_flags, num+1);
302 if (nodemap->node == NULL) {
306 n = &nodemap->node[num];
311 nodemap->num = num+1;
315 /* Read a nodes file into a node map */
316 static struct ctdb_node_map *ctdb_read_nodes_file(TALLOC_CTX *mem_ctx,
322 struct ctdb_node_map *nodemap;
324 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
325 if (nodemap == NULL) {
329 lines = file_lines_load(nlist, &nlines, 0, mem_ctx);
334 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
338 for (i=0; i<nlines; i++) {
344 /* strip leading spaces */
345 while((*node == ' ') || (*node == '\t')) {
351 /* strip trailing spaces */
353 ((node[len-1] == ' ') || (node[len-1] == '\t')))
363 /* A "deleted" node is a node that is
364 commented out in the nodes file. This is
365 used instead of removing a line, which
366 would cause subsequent nodes to change
368 flags = NODE_FLAGS_DELETED;
369 node = discard_const("0.0.0.0");
373 if (! node_map_add(nodemap, node, flags)) {
375 TALLOC_FREE(nodemap);
384 static struct ctdb_node_map *read_nodes_file(TALLOC_CTX *mem_ctx,
387 struct ctdb_node_map *nodemap;
388 char nodes_list[PATH_MAX];
389 const char *ctdb_base;
392 ctdb_base = getenv("CTDB_BASE");
393 if (ctdb_base == NULL) {
394 D_ERR("CTDB_BASE is not set\n");
398 /* read optional node-specific nodes file */
399 num = snprintf(nodes_list, sizeof(nodes_list),
400 "%s/nodes.%d", ctdb_base, pnn);
401 if (num == sizeof(nodes_list)) {
402 D_ERR("nodes file path too long\n");
405 nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
406 if (nodemap != NULL) {
407 /* Fake a load failure for an empty nodemap */
408 if (nodemap->num == 0) {
409 talloc_free(nodemap);
411 D_ERR("Failed to read nodes file \"%s\"\n", nodes_list);
418 /* read normal nodes file */
419 num = snprintf(nodes_list, sizeof(nodes_list), "%s/nodes", ctdb_base);
420 if (num == sizeof(nodes_list)) {
421 D_ERR("nodes file path too long\n");
424 nodemap = ctdb_read_nodes_file(mem_ctx, nodes_list);
425 if (nodemap != NULL) {
429 DBG_ERR("Failed to read nodes file \"%s\"\n", nodes_list);
433 static struct interface_map *interfaces_init(TALLOC_CTX *mem_ctx)
435 struct interface_map *iface_map;
437 iface_map = talloc_zero(mem_ctx, struct interface_map);
438 if (iface_map == NULL) {
445 /* Read interfaces information. Same format as "ctdb ifaces -Y"
447 * :Name:LinkStatus:References:
452 static bool interfaces_parse(struct interface_map *iface_map)
456 while ((fgets(line, sizeof(line), stdin) != NULL)) {
459 char *tok, *t, *name;
460 struct interface *iface;
462 if (line[0] == '\n') {
466 /* Get rid of pesky newline */
467 if ((t = strchr(line, '\n')) != NULL) {
471 if (strcmp(line, ":Name:LinkStatus:References:") == 0) {
475 /* Leading colon... */
476 // tok = strtok(line, ":");
479 tok = strtok(line, ":");
481 fprintf(stderr, "bad line (%s) - missing name\n", line);
487 tok = strtok(NULL, ":");
489 fprintf(stderr, "bad line (%s) - missing link state\n",
493 link_state = (uint16_t)strtoul(tok, NULL, 0);
496 tok = strtok(NULL, ":");
498 fprintf(stderr, "bad line (%s) - missing references\n",
502 references = (uint32_t)strtoul(tok, NULL, 0);
504 iface_map->iface = talloc_realloc(iface_map, iface_map->iface,
507 if (iface_map->iface == NULL) {
511 iface = &iface_map->iface[iface_map->num];
513 iface->name = talloc_strdup(iface_map, name);
514 if (iface->name == NULL) {
517 iface->link_up = link_state;
518 iface->references = references;
523 DEBUG(DEBUG_INFO, ("Parsing interfaces done\n"));
527 fprintf(stderr, "Parsing interfaces failed\n");
531 static struct vnn_map *vnnmap_init(TALLOC_CTX *mem_ctx)
533 struct vnn_map *vnn_map;
535 vnn_map = talloc_zero(mem_ctx, struct vnn_map);
536 if (vnn_map == NULL) {
537 fprintf(stderr, "Memory error\n");
540 vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
541 vnn_map->generation = INVALID_GENERATION;
554 static bool vnnmap_parse(struct vnn_map *vnn_map)
558 while (fgets(line, sizeof(line), stdin) != NULL) {
562 if (line[0] == '\n') {
566 /* Get rid of pesky newline */
567 if ((t = strchr(line, '\n')) != NULL) {
571 n = (uint32_t) strtol(line, NULL, 0);
574 if (vnn_map->generation == INVALID_GENERATION) {
575 vnn_map->generation = n;
579 vnn_map->map = talloc_realloc(vnn_map, vnn_map->map, uint32_t,
581 if (vnn_map->map == NULL) {
582 fprintf(stderr, "Memory error\n");
586 vnn_map->map[vnn_map->size] = n;
590 DEBUG(DEBUG_INFO, ("Parsing vnnmap done\n"));
594 fprintf(stderr, "Parsing vnnmap failed\n");
598 static bool reclock_parse(struct ctdbd_context *ctdb)
603 if (fgets(line, sizeof(line), stdin) == NULL) {
607 if (line[0] == '\n') {
608 /* Recovery lock remains unset */
612 /* Get rid of pesky newline */
613 if ((t = strchr(line, '\n')) != NULL) {
617 ctdb->reclock = talloc_strdup(ctdb, line);
618 if (ctdb->reclock == NULL) {
622 /* Swallow possible blank line following section. Picky
623 * compiler settings don't allow the return value to be
624 * ignored, so make the compiler happy.
626 if (fgets(line, sizeof(line), stdin) == NULL) {
629 DEBUG(DEBUG_INFO, ("Parsing reclock done\n"));
633 fprintf(stderr, "Parsing reclock failed\n");
637 static struct database_map *dbmap_init(TALLOC_CTX *mem_ctx,
640 struct database_map *db_map;
642 db_map = talloc_zero(mem_ctx, struct database_map);
643 if (db_map == NULL) {
647 db_map->dbdir = talloc_strdup(db_map, dbdir);
648 if (db_map->dbdir == NULL) {
656 /* Read a database map from stdin. Each line looks like:
657 * <ID> <NAME> [FLAGS] [SEQ_NUM]
658 * EOF or a blank line terminates input.
660 * By default, flags and seq_num are 0
663 static bool dbmap_parse(struct database_map *db_map)
667 while ((fgets(line, sizeof(line), stdin) != NULL)) {
670 uint32_t seq_num = 0;
675 if (line[0] == '\n') {
679 /* Get rid of pesky newline */
680 if ((t = strchr(line, '\n')) != NULL) {
685 tok = strtok(line, " \t");
687 fprintf(stderr, "bad line (%s) - missing ID\n", line);
690 id = (uint32_t)strtoul(tok, NULL, 0);
693 tok = strtok(NULL, " \t");
695 fprintf(stderr, "bad line (%s) - missing NAME\n", line);
698 name = talloc_strdup(db_map, tok);
704 tok = strtok(NULL, " \t");
705 while (tok != NULL) {
706 if (strcmp(tok, "PERSISTENT") == 0) {
707 flags |= CTDB_DB_FLAGS_PERSISTENT;
708 } else if (strcmp(tok, "STICKY") == 0) {
709 flags |= CTDB_DB_FLAGS_STICKY;
710 } else if (strcmp(tok, "READONLY") == 0) {
711 flags |= CTDB_DB_FLAGS_READONLY;
712 } else if (strcmp(tok, "REPLICATED") == 0) {
713 flags |= CTDB_DB_FLAGS_REPLICATED;
714 } else if (tok[0] >= '0'&& tok[0] <= '9') {
715 uint8_t nv = CTDB_DB_FLAGS_PERSISTENT |
716 CTDB_DB_FLAGS_REPLICATED;
718 if ((flags & nv) == 0) {
720 "seq_num for volatile db\n");
723 seq_num = (uint64_t)strtoull(tok, NULL, 0);
726 tok = strtok(NULL, " \t");
729 db = talloc_zero(db_map, struct database);
735 db->name = talloc_steal(db, name);
736 db->path = talloc_asprintf(db, "%s/%s", db_map->dbdir, name);
737 if (db->path == NULL) {
742 db->seq_num = seq_num;
744 DLIST_ADD_END(db_map->db, db);
747 DEBUG(DEBUG_INFO, ("Parsing dbmap done\n"));
751 DEBUG(DEBUG_INFO, ("Parsing dbmap failed\n"));
756 static struct database *database_find(struct database_map *db_map,
761 for (db = db_map->db; db != NULL; db = db->next) {
762 if (db->id == db_id) {
770 static int database_count(struct database_map *db_map)
775 for (db = db_map->db; db != NULL; db = db->next) {
782 static int database_flags(uint8_t db_flags)
786 if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
787 tdb_flags = TDB_DEFAULT;
789 /* volatile and replicated use the same flags */
790 tdb_flags = TDB_NOSYNC |
792 TDB_INCOMPATIBLE_HASH;
795 tdb_flags |= TDB_DISALLOW_NESTING;
800 static struct database *database_new(struct database_map *db_map,
801 const char *name, uint8_t flags)
807 db = talloc_zero(db_map, struct database);
812 db->name = talloc_strdup(db, name);
813 if (db->name == NULL) {
817 db->path = talloc_asprintf(db, "%s/%s", db_map->dbdir, name);
818 if (db->path == NULL) {
822 key.dsize = strlen(db->name) + 1;
823 key.dptr = discard_const(db->name);
825 db->id = tdb_jenkins_hash(&key);
828 tdb_flags = database_flags(flags);
830 db->tdb = tdb_open(db->path, 8192, tdb_flags, O_CREAT|O_RDWR, 0644);
831 if (db->tdb == NULL) {
832 DBG_ERR("tdb_open\n");
836 DLIST_ADD_END(db_map->db, db);
840 DBG_ERR("Memory error\n");
846 static int ltdb_store(struct database *db, TDB_DATA key,
847 struct ctdb_ltdb_header *header, TDB_DATA data)
850 bool db_volatile = true;
853 if (db->tdb == NULL) {
857 if ((db->flags & CTDB_DB_FLAGS_PERSISTENT) ||
858 (db->flags & CTDB_DB_FLAGS_REPLICATED)) {
862 if (data.dsize > 0) {
865 if (db_volatile && header->rsn == 0) {
873 rec[0].dsize = ctdb_ltdb_header_len(header);
874 rec[0].dptr = (uint8_t *)header;
876 rec[1].dsize = data.dsize;
877 rec[1].dptr = data.dptr;
879 ret = tdb_storev(db->tdb, key, rec, 2, TDB_REPLACE);
881 if (header->rsn > 0) {
882 ret = tdb_delete(db->tdb, key);
891 static int ltdb_fetch(struct database *db, TDB_DATA key,
892 struct ctdb_ltdb_header *header,
893 TALLOC_CTX *mem_ctx, TDB_DATA *data)
899 if (db->tdb == NULL) {
903 rec = tdb_fetch(db->tdb, key);
904 ret = ctdb_ltdb_header_pull(rec.dptr, rec.dsize, header, &np);
906 if (rec.dptr != NULL) {
910 *header = (struct ctdb_ltdb_header) {
916 ret = ltdb_store(db, key, header, tdb_null);
925 data->dsize = rec.dsize - ctdb_ltdb_header_len(header);
926 data->dptr = talloc_memdup(mem_ctx,
927 rec.dptr + ctdb_ltdb_header_len(header),
929 if (data->dptr == NULL) {
937 static int database_seqnum(struct database *db, uint64_t *seqnum)
939 const char *keyname = CTDB_DB_SEQNUM_KEY;
941 struct ctdb_ltdb_header header;
945 if (db->tdb == NULL) {
946 *seqnum = db->seq_num;
950 key.dptr = discard_const(keyname);
951 key.dsize = strlen(keyname) + 1;
953 ret = ltdb_fetch(db, key, &header, db, &data);
958 if (data.dsize == 0) {
963 ret = ctdb_uint64_pull(data.dptr, data.dsize, seqnum, &np);
964 talloc_free(data.dptr);
972 static int ltdb_transaction_update(uint32_t reqid,
973 struct ctdb_ltdb_header *no_header,
974 TDB_DATA key, TDB_DATA data,
977 struct database *db = (struct database *)private_data;
978 TALLOC_CTX *tmp_ctx = talloc_new(db);
979 struct ctdb_ltdb_header header = { 0 }, oldheader;
983 if (db->tdb == NULL) {
987 ret = ctdb_ltdb_header_extract(&data, &header);
992 ret = ltdb_fetch(db, key, &oldheader, tmp_ctx, &olddata);
997 if (olddata.dsize > 0) {
998 if (oldheader.rsn > header.rsn ||
999 (oldheader.rsn == header.rsn &&
1000 olddata.dsize != data.dsize)) {
1005 talloc_free(tmp_ctx);
1007 ret = ltdb_store(db, key, &header, data);
1011 static int ltdb_transaction(struct database *db,
1012 struct ctdb_rec_buffer *recbuf)
1016 if (db->tdb == NULL) {
1020 ret = tdb_transaction_start(db->tdb);
1025 ret = ctdb_rec_buffer_traverse(recbuf, ltdb_transaction_update, db);
1027 tdb_transaction_cancel(db->tdb);
1030 ret = tdb_transaction_commit(db->tdb);
1034 static bool public_ips_parse(struct ctdbd_context *ctdb,
1039 if (numnodes == 0) {
1040 D_ERR("Must initialise nodemap before public IPs\n");
1044 ctdb->known_ips = ipalloc_read_known_ips(ctdb, numnodes, false);
1046 status = (ctdb->known_ips != NULL);
1049 D_INFO("Parsing public IPs done\n");
1051 D_INFO("Parsing public IPs failed\n");
1057 /* Read information about controls to fail. Format is:
1058 * <opcode> <pnn> {ERROR|TIMEOUT} <comment>
1060 static bool control_failures_parse(struct ctdbd_context *ctdb)
1064 while ((fgets(line, sizeof(line), stdin) != NULL)) {
1066 enum ctdb_controls opcode;
1069 const char *comment;
1070 struct fake_control_failure *failure = NULL;
1072 if (line[0] == '\n') {
1076 /* Get rid of pesky newline */
1077 if ((t = strchr(line, '\n')) != NULL) {
1082 tok = strtok(line, " \t");
1084 D_ERR("bad line (%s) - missing opcode\n", line);
1087 opcode = (enum ctdb_controls)strtoul(tok, NULL, 0);
1090 tok = strtok(NULL, " \t");
1092 D_ERR("bad line (%s) - missing PNN\n", line);
1095 pnn = (uint32_t)strtoul(tok, NULL, 0);
1098 tok = strtok(NULL, " \t");
1100 D_ERR("bad line (%s) - missing errno\n", line);
1103 error = talloc_strdup(ctdb, tok);
1104 if (error == NULL) {
1107 if (strcmp(error, "ERROR") != 0 &&
1108 strcmp(error, "TIMEOUT") != 0) {
1109 D_ERR("bad line (%s) "
1110 "- error must be \"ERROR\" or \"TIMEOUT\"\n",
1116 tok = strtok(NULL, "\n"); /* rest of line */
1118 D_ERR("bad line (%s) - missing comment\n", line);
1121 comment = talloc_strdup(ctdb, tok);
1122 if (comment == NULL) {
1126 failure = talloc_zero(ctdb, struct fake_control_failure);
1127 if (failure == NULL) {
1131 failure->opcode = opcode;
1133 failure->error = error;
1134 failure->comment = comment;
1136 DLIST_ADD(ctdb->control_failures, failure);
1139 D_INFO("Parsing fake control failures done\n");
1143 D_INFO("Parsing fake control failures failed\n");
1151 static int ctdb_client_destructor(struct ctdb_client *client)
1153 DLIST_REMOVE(client->ctdb->client_list, client);
1157 static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
1160 struct ctdb_client *client;
1162 client = talloc_zero(client_state, struct ctdb_client);
1163 if (client == NULL) {
1167 client->ctdb = ctdb;
1168 client->pid = client_pid;
1169 client->state = client_state;
1171 DLIST_ADD(ctdb->client_list, client);
1172 talloc_set_destructor(client, ctdb_client_destructor);
1176 static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
1178 struct ctdb_client *client;
1180 for (client=ctdb->client_list; client != NULL; client=client->next) {
1181 if (client->pid == client_pid) {
1182 return client->state;
1190 * CTDB context setup
1193 static uint32_t new_generation(uint32_t old_generation)
1195 uint32_t generation;
1198 generation = random();
1199 if (generation != INVALID_GENERATION &&
1200 generation != old_generation) {
1208 static struct ctdbd_context *ctdbd_setup(TALLOC_CTX *mem_ctx,
1211 struct ctdbd_context *ctdb;
1216 ctdb = talloc_zero(mem_ctx, struct ctdbd_context);
1221 ctdb->node_map = nodemap_init(ctdb);
1222 if (ctdb->node_map == NULL) {
1226 ctdb->iface_map = interfaces_init(ctdb);
1227 if (ctdb->iface_map == NULL) {
1231 ctdb->vnn_map = vnnmap_init(ctdb);
1232 if (ctdb->vnn_map == NULL) {
1236 ctdb->db_map = dbmap_init(ctdb, dbdir);
1237 if (ctdb->db_map == NULL) {
1241 ret = srvid_init(ctdb, &ctdb->srv);
1246 while (fgets(line, sizeof(line), stdin) != NULL) {
1249 if ((t = strchr(line, '\n')) != NULL) {
1253 if (strcmp(line, "NODEMAP") == 0) {
1254 status = nodemap_parse(ctdb->node_map);
1255 } else if (strcmp(line, "IFACES") == 0) {
1256 status = interfaces_parse(ctdb->iface_map);
1257 } else if (strcmp(line, "VNNMAP") == 0) {
1258 status = vnnmap_parse(ctdb->vnn_map);
1259 } else if (strcmp(line, "DBMAP") == 0) {
1260 status = dbmap_parse(ctdb->db_map);
1261 } else if (strcmp(line, "PUBLICIPS") == 0) {
1262 status = public_ips_parse(ctdb,
1263 ctdb->node_map->num_nodes);
1264 } else if (strcmp(line, "RECLOCK") == 0) {
1265 status = reclock_parse(ctdb);
1266 } else if (strcmp(line, "CONTROLFAILS") == 0) {
1267 status = control_failures_parse(ctdb);
1269 fprintf(stderr, "Unknown line %s\n", line);
1278 ctdb->start_time = tevent_timeval_current();
1279 ctdb->recovery_start_time = tevent_timeval_current();
1280 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1281 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
1282 ctdb->vnn_map->generation =
1283 new_generation(ctdb->vnn_map->generation);
1285 ctdb->recovery_end_time = tevent_timeval_current();
1287 ctdb->log_level = DEBUG_ERR;
1288 ctdb->runstate = CTDB_RUNSTATE_RUNNING;
1290 ctdb_tunable_set_defaults(&ctdb->tun_list);
1299 static bool ctdbd_verify(struct ctdbd_context *ctdb)
1304 if (ctdb->node_map->num_nodes == 0) {
1308 /* Make sure all the nodes are in order */
1309 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1310 node = &ctdb->node_map->node[i];
1311 if (node->pnn != i) {
1312 fprintf(stderr, "Expected node %u, found %u\n",
1318 node = &ctdb->node_map->node[ctdb->node_map->pnn];
1319 if (node->flags & NODE_FLAGS_DISCONNECTED) {
1320 DEBUG(DEBUG_INFO, ("Node disconnected, exiting\n"));
1331 struct recover_state {
1332 struct tevent_context *ev;
1333 struct ctdbd_context *ctdb;
1336 static int recover_check(struct tevent_req *req);
1337 static void recover_wait_done(struct tevent_req *subreq);
1338 static void recover_done(struct tevent_req *subreq);
1340 static struct tevent_req *recover_send(TALLOC_CTX *mem_ctx,
1341 struct tevent_context *ev,
1342 struct ctdbd_context *ctdb)
1344 struct tevent_req *req;
1345 struct recover_state *state;
1348 req = tevent_req_create(mem_ctx, &state, struct recover_state);
1356 ret = recover_check(req);
1358 tevent_req_error(req, ret);
1359 return tevent_req_post(req, ev);
1365 static int recover_check(struct tevent_req *req)
1367 struct recover_state *state = tevent_req_data(
1368 req, struct recover_state);
1369 struct ctdbd_context *ctdb = state->ctdb;
1370 struct tevent_req *subreq;
1371 bool recovery_disabled;
1374 recovery_disabled = false;
1375 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1376 if (ctdb->node_map->node[i].recovery_disabled) {
1377 recovery_disabled = true;
1382 subreq = tevent_wakeup_send(state, state->ev,
1383 tevent_timeval_current_ofs(1, 0));
1384 if (subreq == NULL) {
1388 if (recovery_disabled) {
1389 tevent_req_set_callback(subreq, recover_wait_done, req);
1391 ctdb->recovery_start_time = tevent_timeval_current();
1392 tevent_req_set_callback(subreq, recover_done, req);
1398 static void recover_wait_done(struct tevent_req *subreq)
1400 struct tevent_req *req = tevent_req_callback_data(
1401 subreq, struct tevent_req);
1405 status = tevent_wakeup_recv(subreq);
1406 TALLOC_FREE(subreq);
1408 tevent_req_error(req, EIO);
1412 ret = recover_check(req);
1414 tevent_req_error(req, ret);
1418 static void recover_done(struct tevent_req *subreq)
1420 struct tevent_req *req = tevent_req_callback_data(
1421 subreq, struct tevent_req);
1422 struct recover_state *state = tevent_req_data(
1423 req, struct recover_state);
1424 struct ctdbd_context *ctdb = state->ctdb;
1427 status = tevent_wakeup_recv(subreq);
1428 TALLOC_FREE(subreq);
1430 tevent_req_error(req, EIO);
1434 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1435 ctdb->recovery_end_time = tevent_timeval_current();
1436 ctdb->vnn_map->generation = new_generation(ctdb->vnn_map->generation);
1438 tevent_req_done(req);
1441 static bool recover_recv(struct tevent_req *req, int *perr)
1445 if (tevent_req_is_unix_error(req, &err)) {
1456 * Routines for ctdb_req_header
1459 static void header_fix_pnn(struct ctdb_req_header *header,
1460 struct ctdbd_context *ctdb)
1462 if (header->srcnode == CTDB_CURRENT_NODE) {
1463 header->srcnode = ctdb->node_map->pnn;
1466 if (header->destnode == CTDB_CURRENT_NODE) {
1467 header->destnode = ctdb->node_map->pnn;
1471 static struct ctdb_req_header header_reply_call(
1472 struct ctdb_req_header *header,
1473 struct ctdbd_context *ctdb)
1475 struct ctdb_req_header reply_header;
1477 reply_header = (struct ctdb_req_header) {
1478 .ctdb_magic = CTDB_MAGIC,
1479 .ctdb_version = CTDB_PROTOCOL,
1480 .generation = ctdb->vnn_map->generation,
1481 .operation = CTDB_REPLY_CALL,
1482 .destnode = header->srcnode,
1483 .srcnode = header->destnode,
1484 .reqid = header->reqid,
1487 return reply_header;
1490 static struct ctdb_req_header header_reply_control(
1491 struct ctdb_req_header *header,
1492 struct ctdbd_context *ctdb)
1494 struct ctdb_req_header reply_header;
1496 reply_header = (struct ctdb_req_header) {
1497 .ctdb_magic = CTDB_MAGIC,
1498 .ctdb_version = CTDB_PROTOCOL,
1499 .generation = ctdb->vnn_map->generation,
1500 .operation = CTDB_REPLY_CONTROL,
1501 .destnode = header->srcnode,
1502 .srcnode = header->destnode,
1503 .reqid = header->reqid,
1506 return reply_header;
1509 static struct ctdb_req_header header_reply_message(
1510 struct ctdb_req_header *header,
1511 struct ctdbd_context *ctdb)
1513 struct ctdb_req_header reply_header;
1515 reply_header = (struct ctdb_req_header) {
1516 .ctdb_magic = CTDB_MAGIC,
1517 .ctdb_version = CTDB_PROTOCOL,
1518 .generation = ctdb->vnn_map->generation,
1519 .operation = CTDB_REQ_MESSAGE,
1520 .destnode = header->srcnode,
1521 .srcnode = header->destnode,
1525 return reply_header;
1532 struct client_state {
1533 struct tevent_context *ev;
1535 struct ctdbd_context *ctdb;
1538 struct comm_context *comm;
1539 struct srvid_register_state *rstate;
1544 * Send replies to call, controls and messages
1547 static void client_reply_done(struct tevent_req *subreq);
1549 static void client_send_call(struct tevent_req *req,
1550 struct ctdb_req_header *header,
1551 struct ctdb_reply_call *reply)
1553 struct client_state *state = tevent_req_data(
1554 req, struct client_state);
1555 struct ctdbd_context *ctdb = state->ctdb;
1556 struct tevent_req *subreq;
1557 struct ctdb_req_header reply_header;
1559 size_t datalen, buflen;
1562 reply_header = header_reply_call(header, ctdb);
1564 datalen = ctdb_reply_call_len(&reply_header, reply);
1565 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1567 tevent_req_error(req, ret);
1571 ret = ctdb_reply_call_push(&reply_header, reply, buf, &buflen);
1573 tevent_req_error(req, ret);
1577 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1578 if (tevent_req_nomem(subreq, req)) {
1581 tevent_req_set_callback(subreq, client_reply_done, req);
1583 talloc_steal(subreq, buf);
1586 static void client_send_message(struct tevent_req *req,
1587 struct ctdb_req_header *header,
1588 struct ctdb_req_message_data *message)
1590 struct client_state *state = tevent_req_data(
1591 req, struct client_state);
1592 struct ctdbd_context *ctdb = state->ctdb;
1593 struct tevent_req *subreq;
1594 struct ctdb_req_header reply_header;
1596 size_t datalen, buflen;
1599 reply_header = header_reply_message(header, ctdb);
1601 datalen = ctdb_req_message_data_len(&reply_header, message);
1602 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1604 tevent_req_error(req, ret);
1608 ret = ctdb_req_message_data_push(&reply_header, message,
1611 tevent_req_error(req, ret);
1615 DEBUG(DEBUG_INFO, ("message srvid = 0x%"PRIx64"\n", message->srvid));
1617 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1618 if (tevent_req_nomem(subreq, req)) {
1621 tevent_req_set_callback(subreq, client_reply_done, req);
1623 talloc_steal(subreq, buf);
1626 static void client_send_control(struct tevent_req *req,
1627 struct ctdb_req_header *header,
1628 struct ctdb_reply_control *reply)
1630 struct client_state *state = tevent_req_data(
1631 req, struct client_state);
1632 struct ctdbd_context *ctdb = state->ctdb;
1633 struct tevent_req *subreq;
1634 struct ctdb_req_header reply_header;
1636 size_t datalen, buflen;
1639 reply_header = header_reply_control(header, ctdb);
1641 datalen = ctdb_reply_control_len(&reply_header, reply);
1642 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1644 tevent_req_error(req, ret);
1648 ret = ctdb_reply_control_push(&reply_header, reply, buf, &buflen);
1650 tevent_req_error(req, ret);
1654 DEBUG(DEBUG_INFO, ("reply opcode = %u\n", reply->rdata.opcode));
1656 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1657 if (tevent_req_nomem(subreq, req)) {
1660 tevent_req_set_callback(subreq, client_reply_done, req);
1662 talloc_steal(subreq, buf);
1665 static void client_reply_done(struct tevent_req *subreq)
1667 struct tevent_req *req = tevent_req_callback_data(
1668 subreq, struct tevent_req);
1672 status = comm_write_recv(subreq, &ret);
1673 TALLOC_FREE(subreq);
1675 tevent_req_error(req, ret);
1680 * Handling protocol - controls
1683 static void control_process_exists(TALLOC_CTX *mem_ctx,
1684 struct tevent_req *req,
1685 struct ctdb_req_header *header,
1686 struct ctdb_req_control *request)
1688 struct client_state *state = tevent_req_data(
1689 req, struct client_state);
1690 struct ctdbd_context *ctdb = state->ctdb;
1691 struct client_state *cstate;
1692 struct ctdb_reply_control reply;
1694 reply.rdata.opcode = request->opcode;
1696 cstate = client_find(ctdb, request->rdata.data.pid);
1697 if (cstate == NULL) {
1699 reply.errmsg = "No client for PID";
1701 reply.status = kill(request->rdata.data.pid, 0);
1702 reply.errmsg = NULL;
1705 client_send_control(req, header, &reply);
1708 static void control_ping(TALLOC_CTX *mem_ctx,
1709 struct tevent_req *req,
1710 struct ctdb_req_header *header,
1711 struct ctdb_req_control *request)
1713 struct client_state *state = tevent_req_data(
1714 req, struct client_state);
1715 struct ctdbd_context *ctdb = state->ctdb;
1716 struct ctdb_reply_control reply;
1718 reply.rdata.opcode = request->opcode;
1719 reply.status = ctdb->num_clients;
1720 reply.errmsg = NULL;
1722 client_send_control(req, header, &reply);
1725 static void control_getdbpath(TALLOC_CTX *mem_ctx,
1726 struct tevent_req *req,
1727 struct ctdb_req_header *header,
1728 struct ctdb_req_control *request)
1730 struct client_state *state = tevent_req_data(
1731 req, struct client_state);
1732 struct ctdbd_context *ctdb = state->ctdb;
1733 struct ctdb_reply_control reply;
1734 struct database *db;
1736 reply.rdata.opcode = request->opcode;
1738 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1740 reply.status = ENOENT;
1741 reply.errmsg = "Database not found";
1743 reply.rdata.data.db_path =
1744 talloc_strdup(mem_ctx, db->path);
1745 if (reply.rdata.data.db_path == NULL) {
1746 reply.status = ENOMEM;
1747 reply.errmsg = "Memory error";
1750 reply.errmsg = NULL;
1754 client_send_control(req, header, &reply);
1757 static void control_getvnnmap(TALLOC_CTX *mem_ctx,
1758 struct tevent_req *req,
1759 struct ctdb_req_header *header,
1760 struct ctdb_req_control *request)
1762 struct client_state *state = tevent_req_data(
1763 req, struct client_state);
1764 struct ctdbd_context *ctdb = state->ctdb;
1765 struct ctdb_reply_control reply;
1766 struct ctdb_vnn_map *vnnmap;
1768 reply.rdata.opcode = request->opcode;
1770 vnnmap = talloc_zero(mem_ctx, struct ctdb_vnn_map);
1771 if (vnnmap == NULL) {
1772 reply.status = ENOMEM;
1773 reply.errmsg = "Memory error";
1775 vnnmap->generation = ctdb->vnn_map->generation;
1776 vnnmap->size = ctdb->vnn_map->size;
1777 vnnmap->map = ctdb->vnn_map->map;
1779 reply.rdata.data.vnnmap = vnnmap;
1781 reply.errmsg = NULL;
1784 client_send_control(req, header, &reply);
1787 static void control_get_debug(TALLOC_CTX *mem_ctx,
1788 struct tevent_req *req,
1789 struct ctdb_req_header *header,
1790 struct ctdb_req_control *request)
1792 struct client_state *state = tevent_req_data(
1793 req, struct client_state);
1794 struct ctdbd_context *ctdb = state->ctdb;
1795 struct ctdb_reply_control reply;
1797 reply.rdata.opcode = request->opcode;
1798 reply.rdata.data.loglevel = (uint32_t)ctdb->log_level;
1800 reply.errmsg = NULL;
1802 client_send_control(req, header, &reply);
1805 static void control_set_debug(TALLOC_CTX *mem_ctx,
1806 struct tevent_req *req,
1807 struct ctdb_req_header *header,
1808 struct ctdb_req_control *request)
1810 struct client_state *state = tevent_req_data(
1811 req, struct client_state);
1812 struct ctdbd_context *ctdb = state->ctdb;
1813 struct ctdb_reply_control reply;
1815 ctdb->log_level = (int)request->rdata.data.loglevel;
1817 reply.rdata.opcode = request->opcode;
1819 reply.errmsg = NULL;
1821 client_send_control(req, header, &reply);
1824 static void control_get_dbmap(TALLOC_CTX *mem_ctx,
1825 struct tevent_req *req,
1826 struct ctdb_req_header *header,
1827 struct ctdb_req_control *request)
1829 struct client_state *state = tevent_req_data(
1830 req, struct client_state);
1831 struct ctdbd_context *ctdb = state->ctdb;
1832 struct ctdb_reply_control reply;
1833 struct ctdb_dbid_map *dbmap;
1834 struct database *db;
1837 reply.rdata.opcode = request->opcode;
1839 dbmap = talloc_zero(mem_ctx, struct ctdb_dbid_map);
1840 if (dbmap == NULL) {
1844 dbmap->num = database_count(ctdb->db_map);
1845 dbmap->dbs = talloc_zero_array(dbmap, struct ctdb_dbid, dbmap->num);
1846 if (dbmap->dbs == NULL) {
1850 db = ctdb->db_map->db;
1851 for (i = 0; i < dbmap->num; i++) {
1852 dbmap->dbs[i] = (struct ctdb_dbid) {
1860 reply.rdata.data.dbmap = dbmap;
1862 reply.errmsg = NULL;
1863 client_send_control(req, header, &reply);
1868 reply.errmsg = "Memory error";
1869 client_send_control(req, header, &reply);
1872 static void control_get_recmode(TALLOC_CTX *mem_ctx,
1873 struct tevent_req *req,
1874 struct ctdb_req_header *header,
1875 struct ctdb_req_control *request)
1877 struct client_state *state = tevent_req_data(
1878 req, struct client_state);
1879 struct ctdbd_context *ctdb = state->ctdb;
1880 struct ctdb_reply_control reply;
1882 reply.rdata.opcode = request->opcode;
1883 reply.status = ctdb->vnn_map->recmode;
1884 reply.errmsg = NULL;
1886 client_send_control(req, header, &reply);
1889 struct set_recmode_state {
1890 struct tevent_req *req;
1891 struct ctdbd_context *ctdb;
1892 struct ctdb_req_header header;
1893 struct ctdb_reply_control reply;
1896 static void set_recmode_callback(struct tevent_req *subreq)
1898 struct set_recmode_state *substate = tevent_req_callback_data(
1899 subreq, struct set_recmode_state);
1903 status = recover_recv(subreq, &ret);
1904 TALLOC_FREE(subreq);
1906 substate->reply.status = ret;
1907 substate->reply.errmsg = "recovery failed";
1909 substate->reply.status = 0;
1910 substate->reply.errmsg = NULL;
1913 client_send_control(substate->req, &substate->header, &substate->reply);
1914 talloc_free(substate);
1917 static void control_set_recmode(TALLOC_CTX *mem_ctx,
1918 struct tevent_req *req,
1919 struct ctdb_req_header *header,
1920 struct ctdb_req_control *request)
1922 struct client_state *state = tevent_req_data(
1923 req, struct client_state);
1924 struct tevent_req *subreq;
1925 struct ctdbd_context *ctdb = state->ctdb;
1926 struct set_recmode_state *substate;
1927 struct ctdb_reply_control reply;
1929 reply.rdata.opcode = request->opcode;
1931 if (request->rdata.data.recmode == CTDB_RECOVERY_NORMAL) {
1933 reply.errmsg = "Client cannot set recmode to NORMAL";
1937 substate = talloc_zero(ctdb, struct set_recmode_state);
1938 if (substate == NULL) {
1940 reply.errmsg = "Memory error";
1944 substate->req = req;
1945 substate->ctdb = ctdb;
1946 substate->header = *header;
1947 substate->reply.rdata.opcode = request->opcode;
1949 subreq = recover_send(substate, state->ev, state->ctdb);
1950 if (subreq == NULL) {
1951 talloc_free(substate);
1954 tevent_req_set_callback(subreq, set_recmode_callback, substate);
1956 ctdb->vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
1960 client_send_control(req, header, &reply);
1964 static void control_db_attach(TALLOC_CTX *mem_ctx,
1965 struct tevent_req *req,
1966 struct ctdb_req_header *header,
1967 struct ctdb_req_control *request)
1969 struct client_state *state = tevent_req_data(
1970 req, struct client_state);
1971 struct ctdbd_context *ctdb = state->ctdb;
1972 struct ctdb_reply_control reply;
1973 struct database *db;
1975 reply.rdata.opcode = request->opcode;
1977 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
1978 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
1983 db = database_new(ctdb->db_map, request->rdata.data.db_name, 0);
1986 reply.errmsg = "Failed to attach database";
1987 client_send_control(req, header, &reply);
1992 reply.rdata.data.db_id = db->id;
1994 reply.errmsg = NULL;
1995 client_send_control(req, header, &reply);
1998 static void srvid_handler(uint64_t srvid, TDB_DATA data, void *private_data)
2000 printf("Received a message for SRVID 0x%"PRIx64"\n", srvid);
2003 static void control_register_srvid(TALLOC_CTX *mem_ctx,
2004 struct tevent_req *req,
2005 struct ctdb_req_header *header,
2006 struct ctdb_req_control *request)
2008 struct client_state *state = tevent_req_data(
2009 req, struct client_state);
2010 struct ctdbd_context *ctdb = state->ctdb;
2011 struct ctdb_reply_control reply;
2014 reply.rdata.opcode = request->opcode;
2016 ret = srvid_register(ctdb->srv, state, request->srvid,
2017 srvid_handler, state);
2020 reply.errmsg = "Memory error";
2024 DEBUG(DEBUG_INFO, ("Register srvid 0x%"PRIx64"\n", request->srvid));
2027 reply.errmsg = NULL;
2030 client_send_control(req, header, &reply);
2033 static void control_deregister_srvid(TALLOC_CTX *mem_ctx,
2034 struct tevent_req *req,
2035 struct ctdb_req_header *header,
2036 struct ctdb_req_control *request)
2038 struct client_state *state = tevent_req_data(
2039 req, struct client_state);
2040 struct ctdbd_context *ctdb = state->ctdb;
2041 struct ctdb_reply_control reply;
2044 reply.rdata.opcode = request->opcode;
2046 ret = srvid_deregister(ctdb->srv, request->srvid, state);
2049 reply.errmsg = "srvid not registered";
2053 DEBUG(DEBUG_INFO, ("Deregister srvid 0x%"PRIx64"\n", request->srvid));
2056 reply.errmsg = NULL;
2059 client_send_control(req, header, &reply);
2062 static void control_get_dbname(TALLOC_CTX *mem_ctx,
2063 struct tevent_req *req,
2064 struct ctdb_req_header *header,
2065 struct ctdb_req_control *request)
2067 struct client_state *state = tevent_req_data(
2068 req, struct client_state);
2069 struct ctdbd_context *ctdb = state->ctdb;
2070 struct ctdb_reply_control reply;
2071 struct database *db;
2073 reply.rdata.opcode = request->opcode;
2075 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2077 reply.status = ENOENT;
2078 reply.errmsg = "Database not found";
2080 reply.rdata.data.db_name = talloc_strdup(mem_ctx, db->name);
2081 if (reply.rdata.data.db_name == NULL) {
2082 reply.status = ENOMEM;
2083 reply.errmsg = "Memory error";
2086 reply.errmsg = NULL;
2090 client_send_control(req, header, &reply);
2093 static void control_get_pid(TALLOC_CTX *mem_ctx,
2094 struct tevent_req *req,
2095 struct ctdb_req_header *header,
2096 struct ctdb_req_control *request)
2098 struct ctdb_reply_control reply;
2100 reply.rdata.opcode = request->opcode;
2101 reply.status = getpid();
2102 reply.errmsg = NULL;
2104 client_send_control(req, header, &reply);
2107 static void control_get_recmaster(TALLOC_CTX *mem_ctx,
2108 struct tevent_req *req,
2109 struct ctdb_req_header *header,
2110 struct ctdb_req_control *request)
2112 struct client_state *state = tevent_req_data(
2113 req, struct client_state);
2114 struct ctdbd_context *ctdb = state->ctdb;
2115 struct ctdb_reply_control reply;
2117 reply.rdata.opcode = request->opcode;
2118 reply.status = ctdb->node_map->recmaster;
2119 reply.errmsg = NULL;
2121 client_send_control(req, header, &reply);
2124 static void control_get_pnn(TALLOC_CTX *mem_ctx,
2125 struct tevent_req *req,
2126 struct ctdb_req_header *header,
2127 struct ctdb_req_control *request)
2129 struct ctdb_reply_control reply;
2131 reply.rdata.opcode = request->opcode;
2132 reply.status = header->destnode;
2133 reply.errmsg = NULL;
2135 client_send_control(req, header, &reply);
2138 static void control_shutdown(TALLOC_CTX *mem_ctx,
2139 struct tevent_req *req,
2140 struct ctdb_req_header *hdr,
2141 struct ctdb_req_control *request)
2143 struct client_state *state = tevent_req_data(
2144 req, struct client_state);
2149 static void control_set_tunable(TALLOC_CTX *mem_ctx,
2150 struct tevent_req *req,
2151 struct ctdb_req_header *header,
2152 struct ctdb_req_control *request)
2154 struct client_state *state = tevent_req_data(
2155 req, struct client_state);
2156 struct ctdbd_context *ctdb = state->ctdb;
2157 struct ctdb_reply_control reply;
2160 reply.rdata.opcode = request->opcode;
2161 reply.errmsg = NULL;
2163 ret = ctdb_tunable_set_value(&ctdb->tun_list,
2164 request->rdata.data.tunable->name,
2165 request->rdata.data.tunable->value,
2169 } else if (obsolete) {
2175 client_send_control(req, header, &reply);
2178 static void control_get_tunable(TALLOC_CTX *mem_ctx,
2179 struct tevent_req *req,
2180 struct ctdb_req_header *header,
2181 struct ctdb_req_control *request)
2183 struct client_state *state = tevent_req_data(
2184 req, struct client_state);
2185 struct ctdbd_context *ctdb = state->ctdb;
2186 struct ctdb_reply_control reply;
2190 reply.rdata.opcode = request->opcode;
2191 reply.errmsg = NULL;
2193 ret = ctdb_tunable_get_value(&ctdb->tun_list,
2194 request->rdata.data.tun_var, &value);
2198 reply.rdata.data.tun_value = value;
2202 client_send_control(req, header, &reply);
2205 static void control_list_tunables(TALLOC_CTX *mem_ctx,
2206 struct tevent_req *req,
2207 struct ctdb_req_header *header,
2208 struct ctdb_req_control *request)
2210 struct ctdb_reply_control reply;
2211 struct ctdb_var_list *var_list;
2213 reply.rdata.opcode = request->opcode;
2214 reply.errmsg = NULL;
2216 var_list = ctdb_tunable_names(mem_ctx);
2217 if (var_list == NULL) {
2220 reply.rdata.data.tun_var_list = var_list;
2224 client_send_control(req, header, &reply);
2227 static void control_modify_flags(TALLOC_CTX *mem_ctx,
2228 struct tevent_req *req,
2229 struct ctdb_req_header *header,
2230 struct ctdb_req_control *request)
2232 struct client_state *state = tevent_req_data(
2233 req, struct client_state);
2234 struct ctdbd_context *ctdb = state->ctdb;
2235 struct ctdb_node_flag_change *change = request->rdata.data.flag_change;
2236 struct ctdb_reply_control reply;
2239 reply.rdata.opcode = request->opcode;
2241 if ((change->old_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) ||
2242 (change->new_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2244 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
2245 reply.status = EINVAL;
2246 reply.errmsg = "Failed to MODIFY_FLAGS";
2247 client_send_control(req, header, &reply);
2251 /* There's all sorts of broadcast weirdness here. Only change
2252 * the specified node, not the destination node of the
2254 node = &ctdb->node_map->node[change->pnn];
2257 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0 &&
2258 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2259 DEBUG(DEBUG_INFO,("Disabling node %d\n", header->destnode));
2260 node->flags |= NODE_FLAGS_PERMANENTLY_DISABLED;
2265 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0 &&
2266 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0) {
2267 DEBUG(DEBUG_INFO,("Enabling node %d\n", header->destnode));
2268 node->flags &= ~NODE_FLAGS_PERMANENTLY_DISABLED;
2272 DEBUG(DEBUG_INFO, ("Flags unchanged for node %d\n", header->destnode));
2276 reply.errmsg = NULL;
2277 client_send_control(req, header, &reply);
2280 static void control_get_all_tunables(TALLOC_CTX *mem_ctx,
2281 struct tevent_req *req,
2282 struct ctdb_req_header *header,
2283 struct ctdb_req_control *request)
2285 struct client_state *state = tevent_req_data(
2286 req, struct client_state);
2287 struct ctdbd_context *ctdb = state->ctdb;
2288 struct ctdb_reply_control reply;
2290 reply.rdata.opcode = request->opcode;
2291 reply.rdata.data.tun_list = &ctdb->tun_list;
2293 reply.errmsg = NULL;
2295 client_send_control(req, header, &reply);
2298 static void control_db_attach_persistent(TALLOC_CTX *mem_ctx,
2299 struct tevent_req *req,
2300 struct ctdb_req_header *header,
2301 struct ctdb_req_control *request)
2303 struct client_state *state = tevent_req_data(
2304 req, struct client_state);
2305 struct ctdbd_context *ctdb = state->ctdb;
2306 struct ctdb_reply_control reply;
2307 struct database *db;
2309 reply.rdata.opcode = request->opcode;
2311 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
2312 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
2317 db = database_new(ctdb->db_map, request->rdata.data.db_name,
2318 CTDB_DB_FLAGS_PERSISTENT);
2321 reply.errmsg = "Failed to attach database";
2322 client_send_control(req, header, &reply);
2327 reply.rdata.data.db_id = db->id;
2329 reply.errmsg = NULL;
2330 client_send_control(req, header, &reply);
2333 static void control_uptime(TALLOC_CTX *mem_ctx,
2334 struct tevent_req *req,
2335 struct ctdb_req_header *header,
2336 struct ctdb_req_control *request)
2338 struct client_state *state = tevent_req_data(
2339 req, struct client_state);
2340 struct ctdbd_context *ctdb = state->ctdb;
2341 struct ctdb_reply_control reply;
2342 struct ctdb_uptime *uptime;;
2344 reply.rdata.opcode = request->opcode;
2346 uptime = talloc_zero(mem_ctx, struct ctdb_uptime);
2347 if (uptime == NULL) {
2351 uptime->current_time = tevent_timeval_current();
2352 uptime->ctdbd_start_time = ctdb->start_time;
2353 uptime->last_recovery_started = ctdb->recovery_start_time;
2354 uptime->last_recovery_finished = ctdb->recovery_end_time;
2356 reply.rdata.data.uptime = uptime;
2358 reply.errmsg = NULL;
2359 client_send_control(req, header, &reply);
2364 reply.errmsg = "Memory error";
2365 client_send_control(req, header, &reply);
2368 static void control_reload_nodes_file(TALLOC_CTX *mem_ctx,
2369 struct tevent_req *req,
2370 struct ctdb_req_header *header,
2371 struct ctdb_req_control *request)
2373 struct client_state *state = tevent_req_data(
2374 req, struct client_state);
2375 struct ctdbd_context *ctdb = state->ctdb;
2376 struct ctdb_reply_control reply;
2377 struct ctdb_node_map *nodemap;
2378 struct node_map *node_map = ctdb->node_map;
2381 reply.rdata.opcode = request->opcode;
2383 nodemap = read_nodes_file(mem_ctx, header->destnode);
2384 if (nodemap == NULL) {
2388 for (i=0; i<nodemap->num; i++) {
2391 if (i < node_map->num_nodes &&
2392 ctdb_sock_addr_same(&nodemap->node[i].addr,
2393 &node_map->node[i].addr)) {
2397 if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
2400 node = &node_map->node[i];
2402 node->flags |= NODE_FLAGS_DELETED;
2403 ret = ctdb_sock_addr_from_string("0.0.0.0", &node->addr,
2406 /* Can't happen, but Coverity... */
2413 if (i < node_map->num_nodes &&
2414 node_map->node[i].flags & NODE_FLAGS_DELETED) {
2415 node = &node_map->node[i];
2417 node->flags &= ~NODE_FLAGS_DELETED;
2418 node->addr = nodemap->node[i].addr;
2423 node_map->node = talloc_realloc(node_map, node_map->node,
2425 node_map->num_nodes+1);
2426 if (node_map->node == NULL) {
2429 node = &node_map->node[node_map->num_nodes];
2431 node->addr = nodemap->node[i].addr;
2432 node->pnn = nodemap->node[i].pnn;
2434 node->capabilities = CTDB_CAP_DEFAULT;
2435 node->recovery_disabled = false;
2436 node->recovery_substate = NULL;
2438 node_map->num_nodes += 1;
2441 talloc_free(nodemap);
2444 reply.errmsg = NULL;
2445 client_send_control(req, header, &reply);
2450 reply.errmsg = "Memory error";
2451 client_send_control(req, header, &reply);
2454 static void control_get_capabilities(TALLOC_CTX *mem_ctx,
2455 struct tevent_req *req,
2456 struct ctdb_req_header *header,
2457 struct ctdb_req_control *request)
2459 struct client_state *state = tevent_req_data(
2460 req, struct client_state);
2461 struct ctdbd_context *ctdb = state->ctdb;
2462 struct ctdb_reply_control reply;
2466 reply.rdata.opcode = request->opcode;
2468 node = &ctdb->node_map->node[header->destnode];
2469 caps = node->capabilities;
2471 if (node->flags & NODE_FLAGS_FAKE_TIMEOUT) {
2472 /* Don't send reply */
2476 reply.rdata.data.caps = caps;
2478 reply.errmsg = NULL;
2480 client_send_control(req, header, &reply);
2483 static void control_release_ip(TALLOC_CTX *mem_ctx,
2484 struct tevent_req *req,
2485 struct ctdb_req_header *header,
2486 struct ctdb_req_control *request)
2488 struct client_state *state = tevent_req_data(
2489 req, struct client_state);
2490 struct ctdbd_context *ctdb = state->ctdb;
2491 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2492 struct ctdb_reply_control reply;
2493 struct ctdb_public_ip_list *ips = NULL;
2494 struct ctdb_public_ip *t = NULL;
2497 reply.rdata.opcode = request->opcode;
2499 if (ctdb->known_ips == NULL) {
2500 D_INFO("RELEASE_IP %s - not a public IP\n",
2501 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2505 ips = &ctdb->known_ips[header->destnode];
2508 for (i = 0; i < ips->num; i++) {
2509 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2515 D_INFO("RELEASE_IP %s - not a public IP\n",
2516 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2520 if (t->pnn != header->destnode) {
2521 if (header->destnode == ip->pnn) {
2522 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2523 ctdb_sock_addr_to_string(mem_ctx,
2527 reply.errmsg = "RELEASE_IP to TAKE_IP node";
2528 client_send_control(req, header, &reply);
2532 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2533 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2537 D_NOTICE("RELEASE_IP %s - to node %d\n",
2538 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2545 reply.errmsg = NULL;
2546 client_send_control(req, header, &reply);
2549 static void control_takeover_ip(TALLOC_CTX *mem_ctx,
2550 struct tevent_req *req,
2551 struct ctdb_req_header *header,
2552 struct ctdb_req_control *request)
2554 struct client_state *state = tevent_req_data(
2555 req, struct client_state);
2556 struct ctdbd_context *ctdb = state->ctdb;
2557 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2558 struct ctdb_reply_control reply;
2559 struct ctdb_public_ip_list *ips = NULL;
2560 struct ctdb_public_ip *t = NULL;
2563 reply.rdata.opcode = request->opcode;
2565 if (ctdb->known_ips == NULL) {
2566 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2567 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2571 ips = &ctdb->known_ips[header->destnode];
2574 for (i = 0; i < ips->num; i++) {
2575 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2581 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2582 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2586 if (t->pnn == header->destnode) {
2587 D_INFO("TAKEOVER_IP %s - redundant\n",
2588 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2590 D_NOTICE("TAKEOVER_IP %s\n",
2591 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2597 reply.errmsg = NULL;
2598 client_send_control(req, header, &reply);
2601 static void control_get_public_ips(TALLOC_CTX *mem_ctx,
2602 struct tevent_req *req,
2603 struct ctdb_req_header *header,
2604 struct ctdb_req_control *request)
2606 struct client_state *state = tevent_req_data(
2607 req, struct client_state);
2608 struct ctdbd_context *ctdb = state->ctdb;
2609 struct ctdb_reply_control reply;
2610 struct ctdb_public_ip_list *ips = NULL;
2612 reply.rdata.opcode = request->opcode;
2614 if (ctdb->known_ips == NULL) {
2615 /* No IPs defined so create a dummy empty struct and ship it */
2616 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2618 reply.status = ENOMEM;
2619 reply.errmsg = "Memory error";
2625 ips = &ctdb->known_ips[header->destnode];
2627 if (request->flags & CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE) {
2628 /* If runstate is not RUNNING or a node is then return
2629 * no available IPs. Don't worry about interface
2630 * states here - we're not faking down to that level.
2632 if (ctdb->runstate != CTDB_RUNSTATE_RUNNING) {
2633 /* No available IPs: return dummy empty struct */
2634 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2636 reply.status = ENOMEM;
2637 reply.errmsg = "Memory error";
2644 reply.rdata.data.pubip_list = ips;
2646 reply.errmsg = NULL;
2649 client_send_control(req, header, &reply);
2652 static void control_get_nodemap(TALLOC_CTX *mem_ctx,
2653 struct tevent_req *req,
2654 struct ctdb_req_header *header,
2655 struct ctdb_req_control *request)
2657 struct client_state *state = tevent_req_data(
2658 req, struct client_state);
2659 struct ctdbd_context *ctdb = state->ctdb;
2660 struct ctdb_reply_control reply;
2661 struct ctdb_node_map *nodemap;
2665 reply.rdata.opcode = request->opcode;
2667 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
2668 if (nodemap == NULL) {
2672 nodemap->num = ctdb->node_map->num_nodes;
2673 nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2675 if (nodemap->node == NULL) {
2679 for (i=0; i<nodemap->num; i++) {
2680 node = &ctdb->node_map->node[i];
2681 nodemap->node[i] = (struct ctdb_node_and_flags) {
2683 .flags = node->flags,
2688 reply.rdata.data.nodemap = nodemap;
2690 reply.errmsg = NULL;
2691 client_send_control(req, header, &reply);
2696 reply.errmsg = "Memory error";
2697 client_send_control(req, header, &reply);
2700 static void control_get_reclock_file(TALLOC_CTX *mem_ctx,
2701 struct tevent_req *req,
2702 struct ctdb_req_header *header,
2703 struct ctdb_req_control *request)
2705 struct client_state *state = tevent_req_data(
2706 req, struct client_state);
2707 struct ctdbd_context *ctdb = state->ctdb;
2708 struct ctdb_reply_control reply;
2710 reply.rdata.opcode = request->opcode;
2712 if (ctdb->reclock != NULL) {
2713 reply.rdata.data.reclock_file =
2714 talloc_strdup(mem_ctx, ctdb->reclock);
2715 if (reply.rdata.data.reclock_file == NULL) {
2716 reply.status = ENOMEM;
2717 reply.errmsg = "Memory error";
2721 reply.rdata.data.reclock_file = NULL;
2725 reply.errmsg = NULL;
2728 client_send_control(req, header, &reply);
2731 static void control_stop_node(TALLOC_CTX *mem_ctx,
2732 struct tevent_req *req,
2733 struct ctdb_req_header *header,
2734 struct ctdb_req_control *request)
2736 struct client_state *state = tevent_req_data(
2737 req, struct client_state);
2738 struct ctdbd_context *ctdb = state->ctdb;
2739 struct ctdb_reply_control reply;
2741 reply.rdata.opcode = request->opcode;
2743 DEBUG(DEBUG_INFO, ("Stopping node\n"));
2744 ctdb->node_map->node[header->destnode].flags |= NODE_FLAGS_STOPPED;
2747 reply.errmsg = NULL;
2749 client_send_control(req, header, &reply);
2753 static void control_continue_node(TALLOC_CTX *mem_ctx,
2754 struct tevent_req *req,
2755 struct ctdb_req_header *header,
2756 struct ctdb_req_control *request)
2758 struct client_state *state = tevent_req_data(
2759 req, struct client_state);
2760 struct ctdbd_context *ctdb = state->ctdb;
2761 struct ctdb_reply_control reply;
2763 reply.rdata.opcode = request->opcode;
2765 DEBUG(DEBUG_INFO, ("Continue node\n"));
2766 ctdb->node_map->node[header->destnode].flags &= ~NODE_FLAGS_STOPPED;
2769 reply.errmsg = NULL;
2771 client_send_control(req, header, &reply);
2775 static void set_ban_state_callback(struct tevent_req *subreq)
2777 struct node *node = tevent_req_callback_data(
2778 subreq, struct node);
2781 status = tevent_wakeup_recv(subreq);
2782 TALLOC_FREE(subreq);
2784 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2787 node->flags &= ~NODE_FLAGS_BANNED;
2790 static void control_set_ban_state(TALLOC_CTX *mem_ctx,
2791 struct tevent_req *req,
2792 struct ctdb_req_header *header,
2793 struct ctdb_req_control *request)
2795 struct client_state *state = tevent_req_data(
2796 req, struct client_state);
2797 struct tevent_req *subreq;
2798 struct ctdbd_context *ctdb = state->ctdb;
2799 struct ctdb_ban_state *ban = request->rdata.data.ban_state;
2800 struct ctdb_reply_control reply;
2803 reply.rdata.opcode = request->opcode;
2805 if (ban->pnn != header->destnode) {
2807 ("SET_BAN_STATE control for PNN %d rejected\n",
2809 reply.status = EINVAL;
2813 node = &ctdb->node_map->node[header->destnode];
2815 if (ban->time == 0) {
2816 DEBUG(DEBUG_INFO,("Unbanning this node\n"));
2817 node->flags &= ~NODE_FLAGS_BANNED;
2821 subreq = tevent_wakeup_send(ctdb->node_map, state->ev,
2822 tevent_timeval_current_ofs(
2824 if (subreq == NULL) {
2825 reply.status = ENOMEM;
2828 tevent_req_set_callback(subreq, set_ban_state_callback, node);
2830 DEBUG(DEBUG_INFO, ("Banning this node for %d seconds\n", ban->time));
2831 node->flags |= NODE_FLAGS_BANNED;
2832 ctdb->vnn_map->generation = INVALID_GENERATION;
2836 reply.errmsg = NULL;
2838 client_send_control(req, header, &reply);
2842 reply.errmsg = "Failed to ban node";
2845 static void control_trans3_commit(TALLOC_CTX *mem_ctx,
2846 struct tevent_req *req,
2847 struct ctdb_req_header *header,
2848 struct ctdb_req_control *request)
2850 struct client_state *state = tevent_req_data(
2851 req, struct client_state);
2852 struct ctdbd_context *ctdb = state->ctdb;
2853 struct ctdb_reply_control reply;
2854 struct database *db;
2857 reply.rdata.opcode = request->opcode;
2859 db = database_find(ctdb->db_map, request->rdata.data.recbuf->db_id);
2862 reply.errmsg = "Unknown database";
2863 client_send_control(req, header, &reply);
2868 (CTDB_DB_FLAGS_PERSISTENT|CTDB_DB_FLAGS_REPLICATED))) {
2870 reply.errmsg = "Transactions on volatile database";
2871 client_send_control(req, header, &reply);
2875 ret = ltdb_transaction(db, request->rdata.data.recbuf);
2878 reply.errmsg = "Transaction failed";
2879 client_send_control(req, header, &reply);
2884 reply.errmsg = NULL;
2885 client_send_control(req, header, &reply);
2888 static void control_get_db_seqnum(TALLOC_CTX *mem_ctx,
2889 struct tevent_req *req,
2890 struct ctdb_req_header *header,
2891 struct ctdb_req_control *request)
2893 struct client_state *state = tevent_req_data(
2894 req, struct client_state);
2895 struct ctdbd_context *ctdb = state->ctdb;
2896 struct ctdb_reply_control reply;
2897 struct database *db;
2900 reply.rdata.opcode = request->opcode;
2902 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2904 reply.status = ENOENT;
2905 reply.errmsg = "Database not found";
2909 ret = database_seqnum(db, &seqnum);
2911 reply.rdata.data.seqnum = seqnum;
2913 reply.errmsg = NULL;
2916 reply.errmsg = "Failed to get seqnum";
2920 client_send_control(req, header, &reply);
2923 static void control_db_get_health(TALLOC_CTX *mem_ctx,
2924 struct tevent_req *req,
2925 struct ctdb_req_header *header,
2926 struct ctdb_req_control *request)
2928 struct client_state *state = tevent_req_data(
2929 req, struct client_state);
2930 struct ctdbd_context *ctdb = state->ctdb;
2931 struct ctdb_reply_control reply;
2932 struct database *db;
2934 reply.rdata.opcode = request->opcode;
2936 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2938 reply.status = ENOENT;
2939 reply.errmsg = "Database not found";
2941 reply.rdata.data.reason = NULL;
2943 reply.errmsg = NULL;
2946 client_send_control(req, header, &reply);
2949 static struct ctdb_iface_list *get_ctdb_iface_list(TALLOC_CTX *mem_ctx,
2950 struct ctdbd_context *ctdb)
2952 struct ctdb_iface_list *iface_list;
2953 struct interface *iface;
2956 iface_list = talloc_zero(mem_ctx, struct ctdb_iface_list);
2957 if (iface_list == NULL) {
2961 iface_list->num = ctdb->iface_map->num;
2962 iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2964 if (iface_list->iface == NULL) {
2965 TALLOC_FREE(iface_list);
2969 for (i=0; i<iface_list->num; i++) {
2970 iface = &ctdb->iface_map->iface[i];
2971 iface_list->iface[i] = (struct ctdb_iface) {
2972 .link_state = iface->link_up,
2973 .references = iface->references,
2975 strlcpy(iface_list->iface[i].name, iface->name,
2976 sizeof(iface_list->iface[i].name));
2983 static void control_get_public_ip_info(TALLOC_CTX *mem_ctx,
2984 struct tevent_req *req,
2985 struct ctdb_req_header *header,
2986 struct ctdb_req_control *request)
2988 struct client_state *state = tevent_req_data(
2989 req, struct client_state);
2990 struct ctdbd_context *ctdb = state->ctdb;
2991 struct ctdb_reply_control reply;
2992 ctdb_sock_addr *addr = request->rdata.data.addr;
2993 struct ctdb_public_ip_list *known = NULL;
2994 struct ctdb_public_ip_info *info = NULL;
2997 reply.rdata.opcode = request->opcode;
2999 info = talloc_zero(mem_ctx, struct ctdb_public_ip_info);
3001 reply.status = ENOMEM;
3002 reply.errmsg = "Memory error";
3006 reply.rdata.data.ipinfo = info;
3008 if (ctdb->known_ips != NULL) {
3009 known = &ctdb->known_ips[header->destnode];
3011 /* No IPs defined so create a dummy empty struct and
3012 * fall through. The given IP won't be matched
3015 known = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
3016 if (known == NULL) {
3017 reply.status = ENOMEM;
3018 reply.errmsg = "Memory error";
3023 for (i = 0; i < known->num; i++) {
3024 if (ctdb_sock_addr_same_ip(&known->ip[i].addr,
3030 if (i == known->num) {
3031 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
3032 ctdb_sock_addr_to_string(mem_ctx, addr, false));
3034 reply.errmsg = "Unknown address";
3038 info->ip = known->ip[i];
3040 /* The fake PUBLICIPS stanza and resulting known_ips data
3041 * don't know anything about interfaces, so completely fake
3044 info->active_idx = 0;
3046 info->ifaces = get_ctdb_iface_list(mem_ctx, ctdb);
3047 if (info->ifaces == NULL) {
3048 reply.status = ENOMEM;
3049 reply.errmsg = "Memory error";
3054 reply.errmsg = NULL;
3057 client_send_control(req, header, &reply);
3060 static void control_get_ifaces(TALLOC_CTX *mem_ctx,
3061 struct tevent_req *req,
3062 struct ctdb_req_header *header,
3063 struct ctdb_req_control *request)
3065 struct client_state *state = tevent_req_data(
3066 req, struct client_state);
3067 struct ctdbd_context *ctdb = state->ctdb;
3068 struct ctdb_reply_control reply;
3069 struct ctdb_iface_list *iface_list;
3071 reply.rdata.opcode = request->opcode;
3073 iface_list = get_ctdb_iface_list(mem_ctx, ctdb);
3074 if (iface_list == NULL) {
3078 reply.rdata.data.iface_list = iface_list;
3080 reply.errmsg = NULL;
3081 client_send_control(req, header, &reply);
3086 reply.errmsg = "Memory error";
3087 client_send_control(req, header, &reply);
3090 static void control_set_iface_link_state(TALLOC_CTX *mem_ctx,
3091 struct tevent_req *req,
3092 struct ctdb_req_header *header,
3093 struct ctdb_req_control *request)
3095 struct client_state *state = tevent_req_data(
3096 req, struct client_state);
3097 struct ctdbd_context *ctdb = state->ctdb;
3098 struct ctdb_reply_control reply;
3099 struct ctdb_iface *in_iface;
3100 struct interface *iface = NULL;
3101 bool link_up = false;
3104 reply.rdata.opcode = request->opcode;
3106 in_iface = request->rdata.data.iface;
3108 if (in_iface->name[CTDB_IFACE_SIZE] != '\0') {
3109 reply.errmsg = "interface name not terminated";
3113 switch (in_iface->link_state) {
3123 reply.errmsg = "invalid link state";
3127 if (in_iface->references != 0) {
3128 reply.errmsg = "references should be 0";
3132 for (i=0; i<ctdb->iface_map->num; i++) {
3133 if (strcmp(ctdb->iface_map->iface[i].name,
3134 in_iface->name) == 0) {
3135 iface = &ctdb->iface_map->iface[i];
3140 if (iface == NULL) {
3141 reply.errmsg = "interface not found";
3145 iface->link_up = link_up;
3148 reply.errmsg = NULL;
3149 client_send_control(req, header, &reply);
3154 client_send_control(req, header, &reply);
3157 static void control_set_db_readonly(TALLOC_CTX *mem_ctx,
3158 struct tevent_req *req,
3159 struct ctdb_req_header *header,
3160 struct ctdb_req_control *request)
3162 struct client_state *state = tevent_req_data(
3163 req, struct client_state);
3164 struct ctdbd_context *ctdb = state->ctdb;
3165 struct ctdb_reply_control reply;
3166 struct database *db;
3168 reply.rdata.opcode = request->opcode;
3170 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3172 reply.status = ENOENT;
3173 reply.errmsg = "Database not found";
3177 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3178 reply.status = EINVAL;
3179 reply.errmsg = "Can not set READONLY on persistent db";
3183 db->flags |= CTDB_DB_FLAGS_READONLY;
3185 reply.errmsg = NULL;
3188 client_send_control(req, header, &reply);
3191 struct traverse_start_ext_state {
3192 struct tevent_req *req;
3193 struct ctdb_req_header *header;
3196 bool withemptyrecords;
3200 static int traverse_start_ext_handler(struct tdb_context *tdb,
3201 TDB_DATA key, TDB_DATA data,
3204 struct traverse_start_ext_state *state =
3205 (struct traverse_start_ext_state *)private_data;
3206 struct ctdb_rec_data rec;
3207 struct ctdb_req_message_data message;
3210 if (data.dsize < sizeof(struct ctdb_ltdb_header)) {
3214 if ((data.dsize == sizeof(struct ctdb_ltdb_header)) &&
3215 (!state->withemptyrecords)) {
3219 rec = (struct ctdb_rec_data) {
3220 .reqid = state->reqid,
3226 message.srvid = state->srvid;
3227 message.data.dsize = ctdb_rec_data_len(&rec);
3228 message.data.dptr = talloc_size(state->req, message.data.dsize);
3229 if (message.data.dptr == NULL) {
3230 state->status = ENOMEM;
3234 ctdb_rec_data_push(&rec, message.data.dptr, &np);
3235 client_send_message(state->req, state->header, &message);
3237 talloc_free(message.data.dptr);
3242 static void control_traverse_start_ext(TALLOC_CTX *mem_ctx,
3243 struct tevent_req *req,
3244 struct ctdb_req_header *header,
3245 struct ctdb_req_control *request)
3247 struct client_state *state = tevent_req_data(
3248 req, struct client_state);
3249 struct ctdbd_context *ctdb = state->ctdb;
3250 struct ctdb_reply_control reply;
3251 struct database *db;
3252 struct ctdb_traverse_start_ext *ext;
3253 struct traverse_start_ext_state t_state;
3254 struct ctdb_rec_data rec;
3255 struct ctdb_req_message_data message;
3260 reply.rdata.opcode = request->opcode;
3262 ext = request->rdata.data.traverse_start_ext;
3264 db = database_find(ctdb->db_map, ext->db_id);
3267 reply.errmsg = "Unknown database";
3268 client_send_control(req, header, &reply);
3272 t_state = (struct traverse_start_ext_state) {
3275 .reqid = ext->reqid,
3276 .srvid = ext->srvid,
3277 .withemptyrecords = ext->withemptyrecords,
3280 ret = tdb_traverse_read(db->tdb, traverse_start_ext_handler, &t_state);
3281 DEBUG(DEBUG_INFO, ("traversed %d records\n", ret));
3282 if (t_state.status != 0) {
3284 reply.errmsg = "Memory error";
3285 client_send_control(req, header, &reply);
3289 client_send_control(req, header, &reply);
3291 rec = (struct ctdb_rec_data) {
3292 .reqid = ext->reqid,
3298 message.srvid = ext->srvid;
3299 message.data.dsize = ctdb_rec_data_len(&rec);
3300 ctdb_rec_data_push(&rec, buffer, &np);
3301 message.data.dptr = buffer;
3302 client_send_message(req, header, &message);
3305 static void control_set_db_sticky(TALLOC_CTX *mem_ctx,
3306 struct tevent_req *req,
3307 struct ctdb_req_header *header,
3308 struct ctdb_req_control *request)
3310 struct client_state *state = tevent_req_data(
3311 req, struct client_state);
3312 struct ctdbd_context *ctdb = state->ctdb;
3313 struct ctdb_reply_control reply;
3314 struct database *db;
3316 reply.rdata.opcode = request->opcode;
3318 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3320 reply.status = ENOENT;
3321 reply.errmsg = "Database not found";
3325 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3326 reply.status = EINVAL;
3327 reply.errmsg = "Can not set STICKY on persistent db";
3331 db->flags |= CTDB_DB_FLAGS_STICKY;
3333 reply.errmsg = NULL;
3336 client_send_control(req, header, &reply);
3339 static void control_ipreallocated(TALLOC_CTX *mem_ctx,
3340 struct tevent_req *req,
3341 struct ctdb_req_header *header,
3342 struct ctdb_req_control *request)
3344 struct ctdb_reply_control reply;
3346 /* Always succeed */
3347 reply.rdata.opcode = request->opcode;
3349 reply.errmsg = NULL;
3351 client_send_control(req, header, &reply);
3354 static void control_get_runstate(TALLOC_CTX *mem_ctx,
3355 struct tevent_req *req,
3356 struct ctdb_req_header *header,
3357 struct ctdb_req_control *request)
3359 struct client_state *state = tevent_req_data(
3360 req, struct client_state);
3361 struct ctdbd_context *ctdb = state->ctdb;
3362 struct ctdb_reply_control reply;
3364 reply.rdata.opcode = request->opcode;
3365 reply.rdata.data.runstate = ctdb->runstate;
3367 reply.errmsg = NULL;
3369 client_send_control(req, header, &reply);
3372 static void control_get_nodes_file(TALLOC_CTX *mem_ctx,
3373 struct tevent_req *req,
3374 struct ctdb_req_header *header,
3375 struct ctdb_req_control *request)
3377 struct ctdb_reply_control reply;
3378 struct ctdb_node_map *nodemap;
3380 reply.rdata.opcode = request->opcode;
3382 nodemap = read_nodes_file(mem_ctx, header->destnode);
3383 if (nodemap == NULL) {
3387 reply.rdata.data.nodemap = nodemap;
3389 reply.errmsg = NULL;
3390 client_send_control(req, header, &reply);
3395 reply.errmsg = "Failed to read nodes file";
3396 client_send_control(req, header, &reply);
3399 static void control_db_open_flags(TALLOC_CTX *mem_ctx,
3400 struct tevent_req *req,
3401 struct ctdb_req_header *header,
3402 struct ctdb_req_control *request)
3404 struct client_state *state = tevent_req_data(
3405 req, struct client_state);
3406 struct ctdbd_context *ctdb = state->ctdb;
3407 struct ctdb_reply_control reply;
3408 struct database *db;
3410 reply.rdata.opcode = request->opcode;
3412 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3414 reply.status = ENOENT;
3415 reply.errmsg = "Database not found";
3417 reply.rdata.data.tdb_flags = database_flags(db->flags);
3419 reply.errmsg = NULL;
3422 client_send_control(req, header, &reply);
3425 static void control_db_attach_replicated(TALLOC_CTX *mem_ctx,
3426 struct tevent_req *req,
3427 struct ctdb_req_header *header,
3428 struct ctdb_req_control *request)
3430 struct client_state *state = tevent_req_data(
3431 req, struct client_state);
3432 struct ctdbd_context *ctdb = state->ctdb;
3433 struct ctdb_reply_control reply;
3434 struct database *db;
3436 reply.rdata.opcode = request->opcode;
3438 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
3439 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
3444 db = database_new(ctdb->db_map, request->rdata.data.db_name,
3445 CTDB_DB_FLAGS_REPLICATED);
3448 reply.errmsg = "Failed to attach database";
3449 client_send_control(req, header, &reply);
3454 reply.rdata.data.db_id = db->id;
3456 reply.errmsg = NULL;
3457 client_send_control(req, header, &reply);
3460 static void control_check_pid_srvid(TALLOC_CTX *mem_ctx,
3461 struct tevent_req *req,
3462 struct ctdb_req_header *header,
3463 struct ctdb_req_control *request)
3465 struct client_state *state = tevent_req_data(
3466 req, struct client_state);
3467 struct ctdbd_context *ctdb = state->ctdb;
3468 struct ctdb_client *client;
3469 struct client_state *cstate;
3470 struct ctdb_reply_control reply;
3471 bool pid_found, srvid_found;
3474 reply.rdata.opcode = request->opcode;
3477 srvid_found = false;
3479 for (client=ctdb->client_list; client != NULL; client=client->next) {
3480 if (client->pid == request->rdata.data.pid_srvid->pid) {
3482 cstate = (struct client_state *)client->state;
3483 ret = srvid_exists(ctdb->srv,
3484 request->rdata.data.pid_srvid->srvid,
3488 ret = kill(cstate->pid, 0);
3491 reply.errmsg = strerror(errno);
3494 reply.errmsg = NULL;
3502 reply.errmsg = "No client for PID";
3503 } else if (! srvid_found) {
3505 reply.errmsg = "No client for PID and SRVID";
3508 client_send_control(req, header, &reply);
3511 static bool fake_control_failure(TALLOC_CTX *mem_ctx,
3512 struct tevent_req *req,
3513 struct ctdb_req_header *header,
3514 struct ctdb_req_control *request)
3516 struct client_state *state = tevent_req_data(
3517 req, struct client_state);
3518 struct ctdbd_context *ctdb = state->ctdb;
3519 struct ctdb_reply_control reply;
3520 struct fake_control_failure *f = NULL;
3522 D_DEBUG("Checking fake control failure for control %u on node %u\n",
3523 request->opcode, header->destnode);
3524 for (f = ctdb->control_failures; f != NULL; f = f->next) {
3525 if (f->opcode == request->opcode &&
3526 (f->pnn == header->destnode ||
3527 f->pnn == CTDB_UNKNOWN_PNN)) {
3529 reply.rdata.opcode = request->opcode;
3530 if (strcmp(f->error, "TIMEOUT") == 0) {
3531 /* Causes no reply */
3532 D_ERR("Control %u fake timeout on node %u\n",
3533 request->opcode, header->destnode);
3535 } else if (strcmp(f->error, "ERROR") == 0) {
3536 D_ERR("Control %u fake error on node %u\n",
3537 request->opcode, header->destnode);
3539 reply.errmsg = f->comment;
3540 client_send_control(req, header, &reply);
3549 static void control_error(TALLOC_CTX *mem_ctx,
3550 struct tevent_req *req,
3551 struct ctdb_req_header *header,
3552 struct ctdb_req_control *request)
3554 struct ctdb_reply_control reply;
3556 D_DEBUG("Control %u not implemented\n", request->opcode);
3558 reply.rdata.opcode = request->opcode;
3560 reply.errmsg = "Not implemented";
3562 client_send_control(req, header, &reply);
3566 * Handling protocol - messages
3569 struct disable_recoveries_state {
3573 static void disable_recoveries_callback(struct tevent_req *subreq)
3575 struct disable_recoveries_state *substate = tevent_req_callback_data(
3576 subreq, struct disable_recoveries_state);
3579 status = tevent_wakeup_recv(subreq);
3580 TALLOC_FREE(subreq);
3582 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
3585 substate->node->recovery_disabled = false;
3586 TALLOC_FREE(substate->node->recovery_substate);
3589 static void message_disable_recoveries(TALLOC_CTX *mem_ctx,
3590 struct tevent_req *req,
3591 struct ctdb_req_header *header,
3592 struct ctdb_req_message *request)
3594 struct client_state *state = tevent_req_data(
3595 req, struct client_state);
3596 struct tevent_req *subreq;
3597 struct ctdbd_context *ctdb = state->ctdb;
3598 struct disable_recoveries_state *substate;
3599 struct ctdb_disable_message *disable = request->data.disable;
3600 struct ctdb_req_message_data reply;
3605 node = &ctdb->node_map->node[header->destnode];
3607 if (disable->timeout == 0) {
3608 TALLOC_FREE(node->recovery_substate);
3609 node->recovery_disabled = false;
3610 DEBUG(DEBUG_INFO, ("Enabled recoveries on node %u\n",
3615 substate = talloc_zero(ctdb->node_map,
3616 struct disable_recoveries_state);
3617 if (substate == NULL) {
3621 substate->node = node;
3623 subreq = tevent_wakeup_send(substate, state->ev,
3624 tevent_timeval_current_ofs(
3625 disable->timeout, 0));
3626 if (subreq == NULL) {
3627 talloc_free(substate);
3630 tevent_req_set_callback(subreq, disable_recoveries_callback, substate);
3632 DEBUG(DEBUG_INFO, ("Disabled recoveries for %d seconds on node %u\n",
3633 disable->timeout, header->destnode));
3634 node->recovery_substate = substate;
3635 node->recovery_disabled = true;
3638 ret = header->destnode;
3641 reply.srvid = disable->srvid;
3642 data.dptr = (uint8_t *)&ret;
3643 data.dsize = sizeof(int);
3646 client_send_message(req, header, &reply);
3649 static void message_takeover_run(TALLOC_CTX *mem_ctx,
3650 struct tevent_req *req,
3651 struct ctdb_req_header *header,
3652 struct ctdb_req_message *request)
3654 struct client_state *state = tevent_req_data(
3655 req, struct client_state);
3656 struct ctdbd_context *ctdb = state->ctdb;
3657 struct ctdb_srvid_message *srvid = request->data.msg;
3658 struct ctdb_req_message_data reply;
3662 if (header->destnode != ctdb->node_map->recmaster) {
3663 /* No reply! Only recmaster replies... */
3667 DEBUG(DEBUG_INFO, ("IP takover run on node %u\n",
3669 ret = header->destnode;
3671 reply.srvid = srvid->srvid;
3672 data.dptr = (uint8_t *)&ret;
3673 data.dsize = sizeof(int);
3676 client_send_message(req, header, &reply);
3680 * Handle a single client
3683 static void client_read_handler(uint8_t *buf, size_t buflen,
3684 void *private_data);
3685 static void client_dead_handler(void *private_data);
3686 static void client_process_packet(struct tevent_req *req,
3687 uint8_t *buf, size_t buflen);
3688 static void client_process_call(struct tevent_req *req,
3689 uint8_t *buf, size_t buflen);
3690 static void client_process_message(struct tevent_req *req,
3691 uint8_t *buf, size_t buflen);
3692 static void client_process_control(struct tevent_req *req,
3693 uint8_t *buf, size_t buflen);
3694 static void client_reply_done(struct tevent_req *subreq);
3696 static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
3697 struct tevent_context *ev,
3698 int fd, struct ctdbd_context *ctdb,
3701 struct tevent_req *req;
3702 struct client_state *state;
3704 socklen_t crl = sizeof(struct ucred);
3707 req = tevent_req_create(mem_ctx, &state, struct client_state);
3717 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
3719 tevent_req_error(req, ret);
3720 return tevent_req_post(req, ev);
3722 state->pid = cr.pid;
3724 ret = comm_setup(state, ev, fd, client_read_handler, req,
3725 client_dead_handler, req, &state->comm);
3727 tevent_req_error(req, ret);
3728 return tevent_req_post(req, ev);
3731 ret = client_add(ctdb, state->pid, state);
3733 tevent_req_error(req, ret);
3734 return tevent_req_post(req, ev);
3737 DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
3742 static void client_read_handler(uint8_t *buf, size_t buflen,
3745 struct tevent_req *req = talloc_get_type_abort(
3746 private_data, struct tevent_req);
3747 struct client_state *state = tevent_req_data(
3748 req, struct client_state);
3749 struct ctdbd_context *ctdb = state->ctdb;
3750 struct ctdb_req_header header;
3754 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3759 if (buflen != header.length) {
3763 ret = ctdb_req_header_verify(&header, 0);
3768 header_fix_pnn(&header, ctdb);
3770 if (header.destnode == CTDB_BROADCAST_ALL) {
3771 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3772 header.destnode = i;
3774 ctdb_req_header_push(&header, buf, &np);
3775 client_process_packet(req, buf, buflen);
3780 if (header.destnode == CTDB_BROADCAST_CONNECTED) {
3781 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3782 if (ctdb->node_map->node[i].flags &
3783 NODE_FLAGS_DISCONNECTED) {
3787 header.destnode = i;
3789 ctdb_req_header_push(&header, buf, &np);
3790 client_process_packet(req, buf, buflen);
3795 if (header.destnode > ctdb->node_map->num_nodes) {
3796 fprintf(stderr, "Invalid destination pnn 0x%x\n",
3802 if (ctdb->node_map->node[header.destnode].flags & NODE_FLAGS_DISCONNECTED) {
3803 fprintf(stderr, "Packet for disconnected node pnn %u\n",
3808 ctdb_req_header_push(&header, buf, &np);
3809 client_process_packet(req, buf, buflen);
3812 static void client_dead_handler(void *private_data)
3814 struct tevent_req *req = talloc_get_type_abort(
3815 private_data, struct tevent_req);
3817 tevent_req_done(req);
3820 static void client_process_packet(struct tevent_req *req,
3821 uint8_t *buf, size_t buflen)
3823 struct ctdb_req_header header;
3827 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3832 switch (header.operation) {
3834 client_process_call(req, buf, buflen);
3837 case CTDB_REQ_MESSAGE:
3838 client_process_message(req, buf, buflen);
3841 case CTDB_REQ_CONTROL:
3842 client_process_control(req, buf, buflen);
3850 static void client_process_call(struct tevent_req *req,
3851 uint8_t *buf, size_t buflen)
3853 struct client_state *state = tevent_req_data(
3854 req, struct client_state);
3855 struct ctdbd_context *ctdb = state->ctdb;
3856 TALLOC_CTX *mem_ctx;
3857 struct ctdb_req_header header;
3858 struct ctdb_req_call request;
3859 struct ctdb_reply_call reply;
3860 struct database *db;
3861 struct ctdb_ltdb_header hdr;
3865 mem_ctx = talloc_new(state);
3866 if (tevent_req_nomem(mem_ctx, req)) {
3870 ret = ctdb_req_call_pull(buf, buflen, &header, mem_ctx, &request);
3872 talloc_free(mem_ctx);
3873 tevent_req_error(req, ret);
3877 header_fix_pnn(&header, ctdb);
3879 if (header.destnode >= ctdb->node_map->num_nodes) {
3883 DEBUG(DEBUG_INFO, ("call db_id = %u\n", request.db_id));
3885 db = database_find(ctdb->db_map, request.db_id);
3890 ret = ltdb_fetch(db, request.key, &hdr, mem_ctx, &data);
3895 /* Fake migration */
3896 if (hdr.dmaster != ctdb->node_map->pnn) {
3897 hdr.dmaster = ctdb->node_map->pnn;
3899 ret = ltdb_store(db, request.key, &hdr, data);
3905 talloc_free(mem_ctx);
3908 reply.data = tdb_null;
3910 client_send_call(req, &header, &reply);
3914 talloc_free(mem_ctx);
3916 reply.data = tdb_null;
3918 client_send_call(req, &header, &reply);
3921 static void client_process_message(struct tevent_req *req,
3922 uint8_t *buf, size_t buflen)
3924 struct client_state *state = tevent_req_data(
3925 req, struct client_state);
3926 struct ctdbd_context *ctdb = state->ctdb;
3927 TALLOC_CTX *mem_ctx;
3928 struct ctdb_req_header header;
3929 struct ctdb_req_message request;
3933 mem_ctx = talloc_new(state);
3934 if (tevent_req_nomem(mem_ctx, req)) {
3938 ret = ctdb_req_message_pull(buf, buflen, &header, mem_ctx, &request);
3940 talloc_free(mem_ctx);
3941 tevent_req_error(req, ret);
3945 header_fix_pnn(&header, ctdb);
3947 if (header.destnode >= ctdb->node_map->num_nodes) {
3948 /* Many messages are not replied to, so just behave as
3949 * though this message was not received */
3950 fprintf(stderr, "Invalid node %d\n", header.destnode);
3951 talloc_free(mem_ctx);
3955 srvid = request.srvid;
3956 DEBUG(DEBUG_INFO, ("request srvid = 0x%"PRIx64"\n", srvid));
3958 if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
3959 message_disable_recoveries(mem_ctx, req, &header, &request);
3960 } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
3961 message_takeover_run(mem_ctx, req, &header, &request);
3963 D_DEBUG("Message id 0x%"PRIx64" not implemented\n", srvid);
3967 talloc_free(mem_ctx);
3970 static void client_process_control(struct tevent_req *req,
3971 uint8_t *buf, size_t buflen)
3973 struct client_state *state = tevent_req_data(
3974 req, struct client_state);
3975 struct ctdbd_context *ctdb = state->ctdb;
3976 TALLOC_CTX *mem_ctx;
3977 struct ctdb_req_header header;
3978 struct ctdb_req_control request;
3981 mem_ctx = talloc_new(state);
3982 if (tevent_req_nomem(mem_ctx, req)) {
3986 ret = ctdb_req_control_pull(buf, buflen, &header, mem_ctx, &request);
3988 talloc_free(mem_ctx);
3989 tevent_req_error(req, ret);
3993 header_fix_pnn(&header, ctdb);
3995 if (header.destnode >= ctdb->node_map->num_nodes) {
3996 struct ctdb_reply_control reply;
3998 reply.rdata.opcode = request.opcode;
3999 reply.errmsg = "Invalid node";
4001 client_send_control(req, &header, &reply);
4005 DEBUG(DEBUG_INFO, ("request opcode = %u, reqid = %u\n",
4006 request.opcode, header.reqid));
4008 if (fake_control_failure(mem_ctx, req, &header, &request)) {
4012 switch (request.opcode) {
4013 case CTDB_CONTROL_PROCESS_EXISTS:
4014 control_process_exists(mem_ctx, req, &header, &request);
4017 case CTDB_CONTROL_PING:
4018 control_ping(mem_ctx, req, &header, &request);
4021 case CTDB_CONTROL_GETDBPATH:
4022 control_getdbpath(mem_ctx, req, &header, &request);
4025 case CTDB_CONTROL_GETVNNMAP:
4026 control_getvnnmap(mem_ctx, req, &header, &request);
4029 case CTDB_CONTROL_GET_DEBUG:
4030 control_get_debug(mem_ctx, req, &header, &request);
4033 case CTDB_CONTROL_SET_DEBUG:
4034 control_set_debug(mem_ctx, req, &header, &request);
4037 case CTDB_CONTROL_GET_DBMAP:
4038 control_get_dbmap(mem_ctx, req, &header, &request);
4041 case CTDB_CONTROL_GET_RECMODE:
4042 control_get_recmode(mem_ctx, req, &header, &request);
4045 case CTDB_CONTROL_SET_RECMODE:
4046 control_set_recmode(mem_ctx, req, &header, &request);
4049 case CTDB_CONTROL_DB_ATTACH:
4050 control_db_attach(mem_ctx, req, &header, &request);
4053 case CTDB_CONTROL_REGISTER_SRVID:
4054 control_register_srvid(mem_ctx, req, &header, &request);
4057 case CTDB_CONTROL_DEREGISTER_SRVID:
4058 control_deregister_srvid(mem_ctx, req, &header, &request);
4061 case CTDB_CONTROL_GET_DBNAME:
4062 control_get_dbname(mem_ctx, req, &header, &request);
4065 case CTDB_CONTROL_GET_PID:
4066 control_get_pid(mem_ctx, req, &header, &request);
4069 case CTDB_CONTROL_GET_RECMASTER:
4070 control_get_recmaster(mem_ctx, req, &header, &request);
4073 case CTDB_CONTROL_GET_PNN:
4074 control_get_pnn(mem_ctx, req, &header, &request);
4077 case CTDB_CONTROL_SHUTDOWN:
4078 control_shutdown(mem_ctx, req, &header, &request);
4081 case CTDB_CONTROL_SET_TUNABLE:
4082 control_set_tunable(mem_ctx, req, &header, &request);
4085 case CTDB_CONTROL_GET_TUNABLE:
4086 control_get_tunable(mem_ctx, req, &header, &request);
4089 case CTDB_CONTROL_LIST_TUNABLES:
4090 control_list_tunables(mem_ctx, req, &header, &request);
4093 case CTDB_CONTROL_MODIFY_FLAGS:
4094 control_modify_flags(mem_ctx, req, &header, &request);
4097 case CTDB_CONTROL_GET_ALL_TUNABLES:
4098 control_get_all_tunables(mem_ctx, req, &header, &request);
4101 case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
4102 control_db_attach_persistent(mem_ctx, req, &header, &request);
4105 case CTDB_CONTROL_UPTIME:
4106 control_uptime(mem_ctx, req, &header, &request);
4109 case CTDB_CONTROL_RELOAD_NODES_FILE:
4110 control_reload_nodes_file(mem_ctx, req, &header, &request);
4113 case CTDB_CONTROL_GET_CAPABILITIES:
4114 control_get_capabilities(mem_ctx, req, &header, &request);
4117 case CTDB_CONTROL_RELEASE_IP:
4118 control_release_ip(mem_ctx, req, &header, &request);
4121 case CTDB_CONTROL_TAKEOVER_IP:
4122 control_takeover_ip(mem_ctx, req, &header, &request);
4125 case CTDB_CONTROL_GET_PUBLIC_IPS:
4126 control_get_public_ips(mem_ctx, req, &header, &request);
4129 case CTDB_CONTROL_GET_NODEMAP:
4130 control_get_nodemap(mem_ctx, req, &header, &request);
4133 case CTDB_CONTROL_GET_RECLOCK_FILE:
4134 control_get_reclock_file(mem_ctx, req, &header, &request);
4137 case CTDB_CONTROL_STOP_NODE:
4138 control_stop_node(mem_ctx, req, &header, &request);
4141 case CTDB_CONTROL_CONTINUE_NODE:
4142 control_continue_node(mem_ctx, req, &header, &request);
4145 case CTDB_CONTROL_SET_BAN_STATE:
4146 control_set_ban_state(mem_ctx, req, &header, &request);
4149 case CTDB_CONTROL_TRANS3_COMMIT:
4150 control_trans3_commit(mem_ctx, req, &header, &request);
4153 case CTDB_CONTROL_GET_DB_SEQNUM:
4154 control_get_db_seqnum(mem_ctx, req, &header, &request);
4157 case CTDB_CONTROL_DB_GET_HEALTH:
4158 control_db_get_health(mem_ctx, req, &header, &request);
4161 case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
4162 control_get_public_ip_info(mem_ctx, req, &header, &request);
4165 case CTDB_CONTROL_GET_IFACES:
4166 control_get_ifaces(mem_ctx, req, &header, &request);
4169 case CTDB_CONTROL_SET_IFACE_LINK_STATE:
4170 control_set_iface_link_state(mem_ctx, req, &header, &request);
4173 case CTDB_CONTROL_SET_DB_READONLY:
4174 control_set_db_readonly(mem_ctx, req, &header, &request);
4177 case CTDB_CONTROL_TRAVERSE_START_EXT:
4178 control_traverse_start_ext(mem_ctx, req, &header, &request);
4181 case CTDB_CONTROL_SET_DB_STICKY:
4182 control_set_db_sticky(mem_ctx, req, &header, &request);
4185 case CTDB_CONTROL_IPREALLOCATED:
4186 control_ipreallocated(mem_ctx, req, &header, &request);
4189 case CTDB_CONTROL_GET_RUNSTATE:
4190 control_get_runstate(mem_ctx, req, &header, &request);
4193 case CTDB_CONTROL_GET_NODES_FILE:
4194 control_get_nodes_file(mem_ctx, req, &header, &request);
4197 case CTDB_CONTROL_DB_OPEN_FLAGS:
4198 control_db_open_flags(mem_ctx, req, &header, &request);
4201 case CTDB_CONTROL_DB_ATTACH_REPLICATED:
4202 control_db_attach_replicated(mem_ctx, req, &header, &request);
4205 case CTDB_CONTROL_CHECK_PID_SRVID:
4206 control_check_pid_srvid(mem_ctx, req, &header, &request);
4210 if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) {
4211 control_error(mem_ctx, req, &header, &request);
4217 talloc_free(mem_ctx);
4220 static int client_recv(struct tevent_req *req, int *perr)
4222 struct client_state *state = tevent_req_data(
4223 req, struct client_state);
4226 DEBUG(DEBUG_INFO, ("Client done fd=%d\n", state->fd));
4229 if (tevent_req_is_unix_error(req, &err)) {
4236 return state->status;
4243 struct server_state {
4244 struct tevent_context *ev;
4245 struct ctdbd_context *ctdb;
4249 static void server_new_client(struct tevent_req *subreq);
4250 static void server_client_done(struct tevent_req *subreq);
4252 static struct tevent_req *server_send(TALLOC_CTX *mem_ctx,
4253 struct tevent_context *ev,
4254 struct ctdbd_context *ctdb,
4257 struct tevent_req *req, *subreq;
4258 struct server_state *state;
4260 req = tevent_req_create(mem_ctx, &state, struct server_state);
4269 subreq = accept_send(state, ev, fd);
4270 if (tevent_req_nomem(subreq, req)) {
4271 return tevent_req_post(req, ev);
4273 tevent_req_set_callback(subreq, server_new_client, req);
4278 static void server_new_client(struct tevent_req *subreq)
4280 struct tevent_req *req = tevent_req_callback_data(
4281 subreq, struct tevent_req);
4282 struct server_state *state = tevent_req_data(
4283 req, struct server_state);
4284 struct ctdbd_context *ctdb = state->ctdb;
4288 client_fd = accept_recv(subreq, NULL, NULL, &ret);
4289 TALLOC_FREE(subreq);
4290 if (client_fd == -1) {
4291 tevent_req_error(req, ret);
4295 subreq = client_send(state, state->ev, client_fd,
4296 ctdb, ctdb->node_map->pnn);
4297 if (tevent_req_nomem(subreq, req)) {
4300 tevent_req_set_callback(subreq, server_client_done, req);
4302 ctdb->num_clients += 1;
4304 subreq = accept_send(state, state->ev, state->fd);
4305 if (tevent_req_nomem(subreq, req)) {
4308 tevent_req_set_callback(subreq, server_new_client, req);
4311 static void server_client_done(struct tevent_req *subreq)
4313 struct tevent_req *req = tevent_req_callback_data(
4314 subreq, struct tevent_req);
4315 struct server_state *state = tevent_req_data(
4316 req, struct server_state);
4317 struct ctdbd_context *ctdb = state->ctdb;
4321 status = client_recv(subreq, &ret);
4322 TALLOC_FREE(subreq);
4324 tevent_req_error(req, ret);
4328 ctdb->num_clients -= 1;
4331 /* Special status, to shutdown server */
4332 DEBUG(DEBUG_INFO, ("Shutting down server\n"));
4333 tevent_req_done(req);
4337 static bool server_recv(struct tevent_req *req, int *perr)
4341 if (tevent_req_is_unix_error(req, &err)) {
4354 static int socket_init(const char *sockpath)
4356 struct sockaddr_un addr;
4360 memset(&addr, 0, sizeof(addr));
4361 addr.sun_family = AF_UNIX;
4363 len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
4364 if (len >= sizeof(addr.sun_path)) {
4365 fprintf(stderr, "path too long: %s\n", sockpath);
4369 fd = socket(AF_UNIX, SOCK_STREAM, 0);
4371 fprintf(stderr, "socket failed - %s\n", sockpath);
4375 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
4377 fprintf(stderr, "bind failed - %s\n", sockpath);
4381 ret = listen(fd, 10);
4383 fprintf(stderr, "listen failed\n");
4387 DEBUG(DEBUG_INFO, ("Socket init done\n"));
4398 static struct options {
4400 const char *sockpath;
4401 const char *pidfile;
4402 const char *debuglevel;
4405 static struct poptOption cmdline_options[] = {
4407 { "dbdir", 'D', POPT_ARG_STRING, &options.dbdir, 0,
4408 "Database directory", "directory" },
4409 { "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
4410 "Unix domain socket path", "filename" },
4411 { "pidfile", 'p', POPT_ARG_STRING, &options.pidfile, 0,
4412 "pid file", "filename" } ,
4413 { "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
4414 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
4418 static void cleanup(void)
4420 unlink(options.sockpath);
4421 unlink(options.pidfile);
4424 static void signal_handler(int sig)
4430 static void start_server(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
4431 struct ctdbd_context *ctdb, int fd, int pfd)
4433 struct tevent_req *req;
4438 signal(SIGTERM, signal_handler);
4440 req = server_send(mem_ctx, ev, ctdb, fd);
4442 fprintf(stderr, "Memory error\n");
4446 len = write(pfd, &ret, sizeof(ret));
4447 if (len != sizeof(ret)) {
4448 fprintf(stderr, "Failed to send message to parent\n");
4453 tevent_req_poll(req, ev);
4455 server_recv(req, &ret);
4461 int main(int argc, const char *argv[])
4463 TALLOC_CTX *mem_ctx;
4464 struct ctdbd_context *ctdb;
4465 struct tevent_context *ev;
4467 int opt, fd, ret, pfd[2];
4472 pc = poptGetContext(argv[0], argc, argv, cmdline_options,
4473 POPT_CONTEXT_KEEP_FIRST);
4474 while ((opt = poptGetNextOpt(pc)) != -1) {
4475 fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
4479 if (options.dbdir == NULL) {
4480 fprintf(stderr, "Please specify database directory\n");
4481 poptPrintHelp(pc, stdout, 0);
4485 if (options.sockpath == NULL) {
4486 fprintf(stderr, "Please specify socket path\n");
4487 poptPrintHelp(pc, stdout, 0);
4491 if (options.pidfile == NULL) {
4492 fprintf(stderr, "Please specify pid file\n");
4493 poptPrintHelp(pc, stdout, 0);
4497 mem_ctx = talloc_new(NULL);
4498 if (mem_ctx == NULL) {
4499 fprintf(stderr, "Memory error\n");
4503 ret = logging_init(mem_ctx, "file:", options.debuglevel, "fake-ctdbd");
4505 fprintf(stderr, "Invalid debug level\n");
4506 poptPrintHelp(pc, stdout, 0);
4510 ctdb = ctdbd_setup(mem_ctx, options.dbdir);
4515 if (! ctdbd_verify(ctdb)) {
4519 ev = tevent_context_init(mem_ctx);
4521 fprintf(stderr, "Memory error\n");
4525 fd = socket_init(options.sockpath);
4532 fprintf(stderr, "Failed to create pipe\n");
4539 fprintf(stderr, "Failed to fork\n");
4547 start_server(mem_ctx, ev, ctdb, fd, pfd[1]);
4554 len = read(pfd[0], &ret, sizeof(ret));
4556 if (len != sizeof(ret)) {
4557 fprintf(stderr, "len = %zi\n", len);
4558 fprintf(stderr, "Failed to get message from child\n");
4563 fp = fopen(options.pidfile, "w");
4565 fprintf(stderr, "Failed to open pid file %s\n",
4570 fprintf(fp, "%d\n", pid);