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 bool public_ips_parse(struct ctdbd_context *ctdb,
978 D_ERR("Must initialise nodemap before public IPs\n");
982 ctdb->known_ips = ipalloc_read_known_ips(ctdb, numnodes, false);
984 status = (ctdb->known_ips != NULL);
987 D_INFO("Parsing public IPs done\n");
989 D_INFO("Parsing public IPs failed\n");
995 /* Read information about controls to fail. Format is:
996 * <opcode> <pnn> {ERROR|TIMEOUT} <comment>
998 static bool control_failures_parse(struct ctdbd_context *ctdb)
1002 while ((fgets(line, sizeof(line), stdin) != NULL)) {
1004 enum ctdb_controls opcode;
1007 const char *comment;
1008 struct fake_control_failure *failure = NULL;
1010 if (line[0] == '\n') {
1014 /* Get rid of pesky newline */
1015 if ((t = strchr(line, '\n')) != NULL) {
1020 tok = strtok(line, " \t");
1022 D_ERR("bad line (%s) - missing opcode\n", line);
1025 opcode = (enum ctdb_controls)strtoul(tok, NULL, 0);
1028 tok = strtok(NULL, " \t");
1030 D_ERR("bad line (%s) - missing PNN\n", line);
1033 pnn = (uint32_t)strtoul(tok, NULL, 0);
1036 tok = strtok(NULL, " \t");
1038 D_ERR("bad line (%s) - missing errno\n", line);
1041 error = talloc_strdup(ctdb, tok);
1042 if (error == NULL) {
1045 if (strcmp(error, "ERROR") != 0 &&
1046 strcmp(error, "TIMEOUT") != 0) {
1047 D_ERR("bad line (%s) "
1048 "- error must be \"ERROR\" or \"TIMEOUT\"\n",
1054 tok = strtok(NULL, "\n"); /* rest of line */
1056 D_ERR("bad line (%s) - missing comment\n", line);
1059 comment = talloc_strdup(ctdb, tok);
1060 if (comment == NULL) {
1064 failure = talloc_zero(ctdb, struct fake_control_failure);
1065 if (failure == NULL) {
1069 failure->opcode = opcode;
1071 failure->error = error;
1072 failure->comment = comment;
1074 DLIST_ADD(ctdb->control_failures, failure);
1077 D_INFO("Parsing fake control failures done\n");
1081 D_INFO("Parsing fake control failures failed\n");
1089 static int ctdb_client_destructor(struct ctdb_client *client)
1091 DLIST_REMOVE(client->ctdb->client_list, client);
1095 static int client_add(struct ctdbd_context *ctdb, pid_t client_pid,
1098 struct ctdb_client *client;
1100 client = talloc_zero(client_state, struct ctdb_client);
1101 if (client == NULL) {
1105 client->ctdb = ctdb;
1106 client->pid = client_pid;
1107 client->state = client_state;
1109 DLIST_ADD(ctdb->client_list, client);
1110 talloc_set_destructor(client, ctdb_client_destructor);
1114 static void *client_find(struct ctdbd_context *ctdb, pid_t client_pid)
1116 struct ctdb_client *client;
1118 for (client=ctdb->client_list; client != NULL; client=client->next) {
1119 if (client->pid == client_pid) {
1120 return client->state;
1128 * CTDB context setup
1131 static uint32_t new_generation(uint32_t old_generation)
1133 uint32_t generation;
1136 generation = random();
1137 if (generation != INVALID_GENERATION &&
1138 generation != old_generation) {
1146 static struct ctdbd_context *ctdbd_setup(TALLOC_CTX *mem_ctx,
1149 struct ctdbd_context *ctdb;
1154 ctdb = talloc_zero(mem_ctx, struct ctdbd_context);
1159 ctdb->node_map = nodemap_init(ctdb);
1160 if (ctdb->node_map == NULL) {
1164 ctdb->iface_map = interfaces_init(ctdb);
1165 if (ctdb->iface_map == NULL) {
1169 ctdb->vnn_map = vnnmap_init(ctdb);
1170 if (ctdb->vnn_map == NULL) {
1174 ctdb->db_map = dbmap_init(ctdb, dbdir);
1175 if (ctdb->db_map == NULL) {
1179 ret = srvid_init(ctdb, &ctdb->srv);
1184 while (fgets(line, sizeof(line), stdin) != NULL) {
1187 if ((t = strchr(line, '\n')) != NULL) {
1191 if (strcmp(line, "NODEMAP") == 0) {
1192 status = nodemap_parse(ctdb->node_map);
1193 } else if (strcmp(line, "IFACES") == 0) {
1194 status = interfaces_parse(ctdb->iface_map);
1195 } else if (strcmp(line, "VNNMAP") == 0) {
1196 status = vnnmap_parse(ctdb->vnn_map);
1197 } else if (strcmp(line, "DBMAP") == 0) {
1198 status = dbmap_parse(ctdb->db_map);
1199 } else if (strcmp(line, "PUBLICIPS") == 0) {
1200 status = public_ips_parse(ctdb,
1201 ctdb->node_map->num_nodes);
1202 } else if (strcmp(line, "RECLOCK") == 0) {
1203 status = reclock_parse(ctdb);
1204 } else if (strcmp(line, "CONTROLFAILS") == 0) {
1205 status = control_failures_parse(ctdb);
1207 fprintf(stderr, "Unknown line %s\n", line);
1216 ctdb->start_time = tevent_timeval_current();
1217 ctdb->recovery_start_time = tevent_timeval_current();
1218 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1219 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
1220 ctdb->vnn_map->generation =
1221 new_generation(ctdb->vnn_map->generation);
1223 ctdb->recovery_end_time = tevent_timeval_current();
1225 ctdb->log_level = DEBUG_ERR;
1226 ctdb->runstate = CTDB_RUNSTATE_RUNNING;
1228 ctdb_tunable_set_defaults(&ctdb->tun_list);
1237 static bool ctdbd_verify(struct ctdbd_context *ctdb)
1242 if (ctdb->node_map->num_nodes == 0) {
1246 /* Make sure all the nodes are in order */
1247 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1248 node = &ctdb->node_map->node[i];
1249 if (node->pnn != i) {
1250 fprintf(stderr, "Expected node %u, found %u\n",
1256 node = &ctdb->node_map->node[ctdb->node_map->pnn];
1257 if (node->flags & NODE_FLAGS_DISCONNECTED) {
1258 DEBUG(DEBUG_INFO, ("Node disconnected, exiting\n"));
1269 struct recover_state {
1270 struct tevent_context *ev;
1271 struct ctdbd_context *ctdb;
1274 static int recover_check(struct tevent_req *req);
1275 static void recover_wait_done(struct tevent_req *subreq);
1276 static void recover_done(struct tevent_req *subreq);
1278 static struct tevent_req *recover_send(TALLOC_CTX *mem_ctx,
1279 struct tevent_context *ev,
1280 struct ctdbd_context *ctdb)
1282 struct tevent_req *req;
1283 struct recover_state *state;
1286 req = tevent_req_create(mem_ctx, &state, struct recover_state);
1294 ret = recover_check(req);
1296 tevent_req_error(req, ret);
1297 return tevent_req_post(req, ev);
1303 static int recover_check(struct tevent_req *req)
1305 struct recover_state *state = tevent_req_data(
1306 req, struct recover_state);
1307 struct ctdbd_context *ctdb = state->ctdb;
1308 struct tevent_req *subreq;
1309 bool recovery_disabled;
1312 recovery_disabled = false;
1313 for (i=0; i<ctdb->node_map->num_nodes; i++) {
1314 if (ctdb->node_map->node[i].recovery_disabled) {
1315 recovery_disabled = true;
1320 subreq = tevent_wakeup_send(state, state->ev,
1321 tevent_timeval_current_ofs(1, 0));
1322 if (subreq == NULL) {
1326 if (recovery_disabled) {
1327 tevent_req_set_callback(subreq, recover_wait_done, req);
1329 ctdb->recovery_start_time = tevent_timeval_current();
1330 tevent_req_set_callback(subreq, recover_done, req);
1336 static void recover_wait_done(struct tevent_req *subreq)
1338 struct tevent_req *req = tevent_req_callback_data(
1339 subreq, struct tevent_req);
1343 status = tevent_wakeup_recv(subreq);
1344 TALLOC_FREE(subreq);
1346 tevent_req_error(req, EIO);
1350 ret = recover_check(req);
1352 tevent_req_error(req, ret);
1356 static void recover_done(struct tevent_req *subreq)
1358 struct tevent_req *req = tevent_req_callback_data(
1359 subreq, struct tevent_req);
1360 struct recover_state *state = tevent_req_data(
1361 req, struct recover_state);
1362 struct ctdbd_context *ctdb = state->ctdb;
1365 status = tevent_wakeup_recv(subreq);
1366 TALLOC_FREE(subreq);
1368 tevent_req_error(req, EIO);
1372 ctdb->vnn_map->recmode = CTDB_RECOVERY_NORMAL;
1373 ctdb->recovery_end_time = tevent_timeval_current();
1374 ctdb->vnn_map->generation = new_generation(ctdb->vnn_map->generation);
1376 tevent_req_done(req);
1379 static bool recover_recv(struct tevent_req *req, int *perr)
1383 if (tevent_req_is_unix_error(req, &err)) {
1394 * Routines for ctdb_req_header
1397 static void header_fix_pnn(struct ctdb_req_header *header,
1398 struct ctdbd_context *ctdb)
1400 if (header->srcnode == CTDB_CURRENT_NODE) {
1401 header->srcnode = ctdb->node_map->pnn;
1404 if (header->destnode == CTDB_CURRENT_NODE) {
1405 header->destnode = ctdb->node_map->pnn;
1409 static struct ctdb_req_header header_reply_call(
1410 struct ctdb_req_header *header,
1411 struct ctdbd_context *ctdb)
1413 struct ctdb_req_header reply_header;
1415 reply_header = (struct ctdb_req_header) {
1416 .ctdb_magic = CTDB_MAGIC,
1417 .ctdb_version = CTDB_PROTOCOL,
1418 .generation = ctdb->vnn_map->generation,
1419 .operation = CTDB_REPLY_CALL,
1420 .destnode = header->srcnode,
1421 .srcnode = header->destnode,
1422 .reqid = header->reqid,
1425 return reply_header;
1428 static struct ctdb_req_header header_reply_control(
1429 struct ctdb_req_header *header,
1430 struct ctdbd_context *ctdb)
1432 struct ctdb_req_header reply_header;
1434 reply_header = (struct ctdb_req_header) {
1435 .ctdb_magic = CTDB_MAGIC,
1436 .ctdb_version = CTDB_PROTOCOL,
1437 .generation = ctdb->vnn_map->generation,
1438 .operation = CTDB_REPLY_CONTROL,
1439 .destnode = header->srcnode,
1440 .srcnode = header->destnode,
1441 .reqid = header->reqid,
1444 return reply_header;
1447 static struct ctdb_req_header header_reply_message(
1448 struct ctdb_req_header *header,
1449 struct ctdbd_context *ctdb)
1451 struct ctdb_req_header reply_header;
1453 reply_header = (struct ctdb_req_header) {
1454 .ctdb_magic = CTDB_MAGIC,
1455 .ctdb_version = CTDB_PROTOCOL,
1456 .generation = ctdb->vnn_map->generation,
1457 .operation = CTDB_REQ_MESSAGE,
1458 .destnode = header->srcnode,
1459 .srcnode = header->destnode,
1463 return reply_header;
1470 struct client_state {
1471 struct tevent_context *ev;
1473 struct ctdbd_context *ctdb;
1476 struct comm_context *comm;
1477 struct srvid_register_state *rstate;
1482 * Send replies to call, controls and messages
1485 static void client_reply_done(struct tevent_req *subreq);
1487 static void client_send_call(struct tevent_req *req,
1488 struct ctdb_req_header *header,
1489 struct ctdb_reply_call *reply)
1491 struct client_state *state = tevent_req_data(
1492 req, struct client_state);
1493 struct ctdbd_context *ctdb = state->ctdb;
1494 struct tevent_req *subreq;
1495 struct ctdb_req_header reply_header;
1497 size_t datalen, buflen;
1500 reply_header = header_reply_call(header, ctdb);
1502 datalen = ctdb_reply_call_len(&reply_header, reply);
1503 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1505 tevent_req_error(req, ret);
1509 ret = ctdb_reply_call_push(&reply_header, reply, buf, &buflen);
1511 tevent_req_error(req, ret);
1515 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1516 if (tevent_req_nomem(subreq, req)) {
1519 tevent_req_set_callback(subreq, client_reply_done, req);
1521 talloc_steal(subreq, buf);
1524 static void client_send_message(struct tevent_req *req,
1525 struct ctdb_req_header *header,
1526 struct ctdb_req_message_data *message)
1528 struct client_state *state = tevent_req_data(
1529 req, struct client_state);
1530 struct ctdbd_context *ctdb = state->ctdb;
1531 struct tevent_req *subreq;
1532 struct ctdb_req_header reply_header;
1534 size_t datalen, buflen;
1537 reply_header = header_reply_message(header, ctdb);
1539 datalen = ctdb_req_message_data_len(&reply_header, message);
1540 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1542 tevent_req_error(req, ret);
1546 ret = ctdb_req_message_data_push(&reply_header, message,
1549 tevent_req_error(req, ret);
1553 DEBUG(DEBUG_INFO, ("message srvid = 0x%"PRIx64"\n", message->srvid));
1555 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1556 if (tevent_req_nomem(subreq, req)) {
1559 tevent_req_set_callback(subreq, client_reply_done, req);
1561 talloc_steal(subreq, buf);
1564 static void client_send_control(struct tevent_req *req,
1565 struct ctdb_req_header *header,
1566 struct ctdb_reply_control *reply)
1568 struct client_state *state = tevent_req_data(
1569 req, struct client_state);
1570 struct ctdbd_context *ctdb = state->ctdb;
1571 struct tevent_req *subreq;
1572 struct ctdb_req_header reply_header;
1574 size_t datalen, buflen;
1577 reply_header = header_reply_control(header, ctdb);
1579 datalen = ctdb_reply_control_len(&reply_header, reply);
1580 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1582 tevent_req_error(req, ret);
1586 ret = ctdb_reply_control_push(&reply_header, reply, buf, &buflen);
1588 tevent_req_error(req, ret);
1592 DEBUG(DEBUG_INFO, ("reply opcode = %u\n", reply->rdata.opcode));
1594 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1595 if (tevent_req_nomem(subreq, req)) {
1598 tevent_req_set_callback(subreq, client_reply_done, req);
1600 talloc_steal(subreq, buf);
1603 static void client_reply_done(struct tevent_req *subreq)
1605 struct tevent_req *req = tevent_req_callback_data(
1606 subreq, struct tevent_req);
1610 status = comm_write_recv(subreq, &ret);
1611 TALLOC_FREE(subreq);
1613 tevent_req_error(req, ret);
1618 * Handling protocol - controls
1621 static void control_process_exists(TALLOC_CTX *mem_ctx,
1622 struct tevent_req *req,
1623 struct ctdb_req_header *header,
1624 struct ctdb_req_control *request)
1626 struct client_state *state = tevent_req_data(
1627 req, struct client_state);
1628 struct ctdbd_context *ctdb = state->ctdb;
1629 struct client_state *cstate;
1630 struct ctdb_reply_control reply;
1632 reply.rdata.opcode = request->opcode;
1634 cstate = client_find(ctdb, request->rdata.data.pid);
1635 if (cstate == NULL) {
1637 reply.errmsg = "No client for PID";
1639 reply.status = kill(request->rdata.data.pid, 0);
1640 reply.errmsg = NULL;
1643 client_send_control(req, header, &reply);
1646 static void control_ping(TALLOC_CTX *mem_ctx,
1647 struct tevent_req *req,
1648 struct ctdb_req_header *header,
1649 struct ctdb_req_control *request)
1651 struct client_state *state = tevent_req_data(
1652 req, struct client_state);
1653 struct ctdbd_context *ctdb = state->ctdb;
1654 struct ctdb_reply_control reply;
1656 reply.rdata.opcode = request->opcode;
1657 reply.status = ctdb->num_clients;
1658 reply.errmsg = NULL;
1660 client_send_control(req, header, &reply);
1663 static void control_getdbpath(TALLOC_CTX *mem_ctx,
1664 struct tevent_req *req,
1665 struct ctdb_req_header *header,
1666 struct ctdb_req_control *request)
1668 struct client_state *state = tevent_req_data(
1669 req, struct client_state);
1670 struct ctdbd_context *ctdb = state->ctdb;
1671 struct ctdb_reply_control reply;
1672 struct database *db;
1674 reply.rdata.opcode = request->opcode;
1676 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1678 reply.status = ENOENT;
1679 reply.errmsg = "Database not found";
1681 reply.rdata.data.db_path =
1682 talloc_strdup(mem_ctx, db->path);
1683 if (reply.rdata.data.db_path == NULL) {
1684 reply.status = ENOMEM;
1685 reply.errmsg = "Memory error";
1688 reply.errmsg = NULL;
1692 client_send_control(req, header, &reply);
1695 static void control_getvnnmap(TALLOC_CTX *mem_ctx,
1696 struct tevent_req *req,
1697 struct ctdb_req_header *header,
1698 struct ctdb_req_control *request)
1700 struct client_state *state = tevent_req_data(
1701 req, struct client_state);
1702 struct ctdbd_context *ctdb = state->ctdb;
1703 struct ctdb_reply_control reply;
1704 struct ctdb_vnn_map *vnnmap;
1706 reply.rdata.opcode = request->opcode;
1708 vnnmap = talloc_zero(mem_ctx, struct ctdb_vnn_map);
1709 if (vnnmap == NULL) {
1710 reply.status = ENOMEM;
1711 reply.errmsg = "Memory error";
1713 vnnmap->generation = ctdb->vnn_map->generation;
1714 vnnmap->size = ctdb->vnn_map->size;
1715 vnnmap->map = ctdb->vnn_map->map;
1717 reply.rdata.data.vnnmap = vnnmap;
1719 reply.errmsg = NULL;
1722 client_send_control(req, header, &reply);
1725 static void control_get_debug(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;
1735 reply.rdata.opcode = request->opcode;
1736 reply.rdata.data.loglevel = (uint32_t)ctdb->log_level;
1738 reply.errmsg = NULL;
1740 client_send_control(req, header, &reply);
1743 static void control_set_debug(TALLOC_CTX *mem_ctx,
1744 struct tevent_req *req,
1745 struct ctdb_req_header *header,
1746 struct ctdb_req_control *request)
1748 struct client_state *state = tevent_req_data(
1749 req, struct client_state);
1750 struct ctdbd_context *ctdb = state->ctdb;
1751 struct ctdb_reply_control reply;
1753 ctdb->log_level = (int)request->rdata.data.loglevel;
1755 reply.rdata.opcode = request->opcode;
1757 reply.errmsg = NULL;
1759 client_send_control(req, header, &reply);
1762 static void control_get_dbmap(TALLOC_CTX *mem_ctx,
1763 struct tevent_req *req,
1764 struct ctdb_req_header *header,
1765 struct ctdb_req_control *request)
1767 struct client_state *state = tevent_req_data(
1768 req, struct client_state);
1769 struct ctdbd_context *ctdb = state->ctdb;
1770 struct ctdb_reply_control reply;
1771 struct ctdb_dbid_map *dbmap;
1772 struct database *db;
1775 reply.rdata.opcode = request->opcode;
1777 dbmap = talloc_zero(mem_ctx, struct ctdb_dbid_map);
1778 if (dbmap == NULL) {
1782 dbmap->num = database_count(ctdb->db_map);
1783 dbmap->dbs = talloc_zero_array(dbmap, struct ctdb_dbid, dbmap->num);
1784 if (dbmap->dbs == NULL) {
1788 db = ctdb->db_map->db;
1789 for (i = 0; i < dbmap->num; i++) {
1790 dbmap->dbs[i] = (struct ctdb_dbid) {
1798 reply.rdata.data.dbmap = dbmap;
1800 reply.errmsg = NULL;
1801 client_send_control(req, header, &reply);
1806 reply.errmsg = "Memory error";
1807 client_send_control(req, header, &reply);
1810 static void control_get_recmode(TALLOC_CTX *mem_ctx,
1811 struct tevent_req *req,
1812 struct ctdb_req_header *header,
1813 struct ctdb_req_control *request)
1815 struct client_state *state = tevent_req_data(
1816 req, struct client_state);
1817 struct ctdbd_context *ctdb = state->ctdb;
1818 struct ctdb_reply_control reply;
1820 reply.rdata.opcode = request->opcode;
1821 reply.status = ctdb->vnn_map->recmode;
1822 reply.errmsg = NULL;
1824 client_send_control(req, header, &reply);
1827 struct set_recmode_state {
1828 struct tevent_req *req;
1829 struct ctdbd_context *ctdb;
1830 struct ctdb_req_header header;
1831 struct ctdb_reply_control reply;
1834 static void set_recmode_callback(struct tevent_req *subreq)
1836 struct set_recmode_state *substate = tevent_req_callback_data(
1837 subreq, struct set_recmode_state);
1841 status = recover_recv(subreq, &ret);
1842 TALLOC_FREE(subreq);
1844 substate->reply.status = ret;
1845 substate->reply.errmsg = "recovery failed";
1847 substate->reply.status = 0;
1848 substate->reply.errmsg = NULL;
1851 client_send_control(substate->req, &substate->header, &substate->reply);
1852 talloc_free(substate);
1855 static void control_set_recmode(TALLOC_CTX *mem_ctx,
1856 struct tevent_req *req,
1857 struct ctdb_req_header *header,
1858 struct ctdb_req_control *request)
1860 struct client_state *state = tevent_req_data(
1861 req, struct client_state);
1862 struct tevent_req *subreq;
1863 struct ctdbd_context *ctdb = state->ctdb;
1864 struct set_recmode_state *substate;
1865 struct ctdb_reply_control reply;
1867 reply.rdata.opcode = request->opcode;
1869 if (request->rdata.data.recmode == CTDB_RECOVERY_NORMAL) {
1871 reply.errmsg = "Client cannot set recmode to NORMAL";
1875 substate = talloc_zero(ctdb, struct set_recmode_state);
1876 if (substate == NULL) {
1878 reply.errmsg = "Memory error";
1882 substate->req = req;
1883 substate->ctdb = ctdb;
1884 substate->header = *header;
1885 substate->reply.rdata.opcode = request->opcode;
1887 subreq = recover_send(substate, state->ev, state->ctdb);
1888 if (subreq == NULL) {
1889 talloc_free(substate);
1892 tevent_req_set_callback(subreq, set_recmode_callback, substate);
1894 ctdb->vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
1898 client_send_control(req, header, &reply);
1902 static void control_db_attach(TALLOC_CTX *mem_ctx,
1903 struct tevent_req *req,
1904 struct ctdb_req_header *header,
1905 struct ctdb_req_control *request)
1907 struct client_state *state = tevent_req_data(
1908 req, struct client_state);
1909 struct ctdbd_context *ctdb = state->ctdb;
1910 struct ctdb_reply_control reply;
1911 struct database *db;
1913 reply.rdata.opcode = request->opcode;
1915 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
1916 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
1921 db = database_new(ctdb->db_map, request->rdata.data.db_name, 0);
1924 reply.errmsg = "Failed to attach database";
1925 client_send_control(req, header, &reply);
1930 reply.rdata.data.db_id = db->id;
1932 reply.errmsg = NULL;
1933 client_send_control(req, header, &reply);
1936 static void srvid_handler(uint64_t srvid, TDB_DATA data, void *private_data)
1938 printf("Received a message for SRVID 0x%"PRIx64"\n", srvid);
1941 static void control_register_srvid(TALLOC_CTX *mem_ctx,
1942 struct tevent_req *req,
1943 struct ctdb_req_header *header,
1944 struct ctdb_req_control *request)
1946 struct client_state *state = tevent_req_data(
1947 req, struct client_state);
1948 struct ctdbd_context *ctdb = state->ctdb;
1949 struct ctdb_reply_control reply;
1952 reply.rdata.opcode = request->opcode;
1954 ret = srvid_register(ctdb->srv, state, request->srvid,
1955 srvid_handler, state);
1958 reply.errmsg = "Memory error";
1962 DEBUG(DEBUG_INFO, ("Register srvid 0x%"PRIx64"\n", request->srvid));
1965 reply.errmsg = NULL;
1968 client_send_control(req, header, &reply);
1971 static void control_deregister_srvid(TALLOC_CTX *mem_ctx,
1972 struct tevent_req *req,
1973 struct ctdb_req_header *header,
1974 struct ctdb_req_control *request)
1976 struct client_state *state = tevent_req_data(
1977 req, struct client_state);
1978 struct ctdbd_context *ctdb = state->ctdb;
1979 struct ctdb_reply_control reply;
1982 reply.rdata.opcode = request->opcode;
1984 ret = srvid_deregister(ctdb->srv, request->srvid, state);
1987 reply.errmsg = "srvid not registered";
1991 DEBUG(DEBUG_INFO, ("Deregister srvid 0x%"PRIx64"\n", request->srvid));
1994 reply.errmsg = NULL;
1997 client_send_control(req, header, &reply);
2000 static void control_get_dbname(TALLOC_CTX *mem_ctx,
2001 struct tevent_req *req,
2002 struct ctdb_req_header *header,
2003 struct ctdb_req_control *request)
2005 struct client_state *state = tevent_req_data(
2006 req, struct client_state);
2007 struct ctdbd_context *ctdb = state->ctdb;
2008 struct ctdb_reply_control reply;
2009 struct database *db;
2011 reply.rdata.opcode = request->opcode;
2013 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2015 reply.status = ENOENT;
2016 reply.errmsg = "Database not found";
2018 reply.rdata.data.db_name = talloc_strdup(mem_ctx, db->name);
2019 if (reply.rdata.data.db_name == NULL) {
2020 reply.status = ENOMEM;
2021 reply.errmsg = "Memory error";
2024 reply.errmsg = NULL;
2028 client_send_control(req, header, &reply);
2031 static void control_get_pid(TALLOC_CTX *mem_ctx,
2032 struct tevent_req *req,
2033 struct ctdb_req_header *header,
2034 struct ctdb_req_control *request)
2036 struct ctdb_reply_control reply;
2038 reply.rdata.opcode = request->opcode;
2039 reply.status = getpid();
2040 reply.errmsg = NULL;
2042 client_send_control(req, header, &reply);
2045 static void control_get_recmaster(TALLOC_CTX *mem_ctx,
2046 struct tevent_req *req,
2047 struct ctdb_req_header *header,
2048 struct ctdb_req_control *request)
2050 struct client_state *state = tevent_req_data(
2051 req, struct client_state);
2052 struct ctdbd_context *ctdb = state->ctdb;
2053 struct ctdb_reply_control reply;
2055 reply.rdata.opcode = request->opcode;
2056 reply.status = ctdb->node_map->recmaster;
2057 reply.errmsg = NULL;
2059 client_send_control(req, header, &reply);
2062 static void control_get_pnn(TALLOC_CTX *mem_ctx,
2063 struct tevent_req *req,
2064 struct ctdb_req_header *header,
2065 struct ctdb_req_control *request)
2067 struct ctdb_reply_control reply;
2069 reply.rdata.opcode = request->opcode;
2070 reply.status = header->destnode;
2071 reply.errmsg = NULL;
2073 client_send_control(req, header, &reply);
2076 static void control_shutdown(TALLOC_CTX *mem_ctx,
2077 struct tevent_req *req,
2078 struct ctdb_req_header *hdr,
2079 struct ctdb_req_control *request)
2081 struct client_state *state = tevent_req_data(
2082 req, struct client_state);
2087 static void control_set_tunable(TALLOC_CTX *mem_ctx,
2088 struct tevent_req *req,
2089 struct ctdb_req_header *header,
2090 struct ctdb_req_control *request)
2092 struct client_state *state = tevent_req_data(
2093 req, struct client_state);
2094 struct ctdbd_context *ctdb = state->ctdb;
2095 struct ctdb_reply_control reply;
2098 reply.rdata.opcode = request->opcode;
2099 reply.errmsg = NULL;
2101 ret = ctdb_tunable_set_value(&ctdb->tun_list,
2102 request->rdata.data.tunable->name,
2103 request->rdata.data.tunable->value,
2107 } else if (obsolete) {
2113 client_send_control(req, header, &reply);
2116 static void control_get_tunable(TALLOC_CTX *mem_ctx,
2117 struct tevent_req *req,
2118 struct ctdb_req_header *header,
2119 struct ctdb_req_control *request)
2121 struct client_state *state = tevent_req_data(
2122 req, struct client_state);
2123 struct ctdbd_context *ctdb = state->ctdb;
2124 struct ctdb_reply_control reply;
2128 reply.rdata.opcode = request->opcode;
2129 reply.errmsg = NULL;
2131 ret = ctdb_tunable_get_value(&ctdb->tun_list,
2132 request->rdata.data.tun_var, &value);
2136 reply.rdata.data.tun_value = value;
2140 client_send_control(req, header, &reply);
2143 static void control_list_tunables(TALLOC_CTX *mem_ctx,
2144 struct tevent_req *req,
2145 struct ctdb_req_header *header,
2146 struct ctdb_req_control *request)
2148 struct ctdb_reply_control reply;
2149 struct ctdb_var_list *var_list;
2151 reply.rdata.opcode = request->opcode;
2152 reply.errmsg = NULL;
2154 var_list = ctdb_tunable_names(mem_ctx);
2155 if (var_list == NULL) {
2158 reply.rdata.data.tun_var_list = var_list;
2162 client_send_control(req, header, &reply);
2165 static void control_modify_flags(TALLOC_CTX *mem_ctx,
2166 struct tevent_req *req,
2167 struct ctdb_req_header *header,
2168 struct ctdb_req_control *request)
2170 struct client_state *state = tevent_req_data(
2171 req, struct client_state);
2172 struct ctdbd_context *ctdb = state->ctdb;
2173 struct ctdb_node_flag_change *change = request->rdata.data.flag_change;
2174 struct ctdb_reply_control reply;
2177 reply.rdata.opcode = request->opcode;
2179 if ((change->old_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) ||
2180 (change->new_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2182 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
2183 reply.status = EINVAL;
2184 reply.errmsg = "Failed to MODIFY_FLAGS";
2185 client_send_control(req, header, &reply);
2189 /* There's all sorts of broadcast weirdness here. Only change
2190 * the specified node, not the destination node of the
2192 node = &ctdb->node_map->node[change->pnn];
2195 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0 &&
2196 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2197 DEBUG(DEBUG_INFO,("Disabling node %d\n", header->destnode));
2198 node->flags |= NODE_FLAGS_PERMANENTLY_DISABLED;
2203 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0 &&
2204 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0) {
2205 DEBUG(DEBUG_INFO,("Enabling node %d\n", header->destnode));
2206 node->flags &= ~NODE_FLAGS_PERMANENTLY_DISABLED;
2210 DEBUG(DEBUG_INFO, ("Flags unchanged for node %d\n", header->destnode));
2214 reply.errmsg = NULL;
2215 client_send_control(req, header, &reply);
2218 static void control_get_all_tunables(TALLOC_CTX *mem_ctx,
2219 struct tevent_req *req,
2220 struct ctdb_req_header *header,
2221 struct ctdb_req_control *request)
2223 struct client_state *state = tevent_req_data(
2224 req, struct client_state);
2225 struct ctdbd_context *ctdb = state->ctdb;
2226 struct ctdb_reply_control reply;
2228 reply.rdata.opcode = request->opcode;
2229 reply.rdata.data.tun_list = &ctdb->tun_list;
2231 reply.errmsg = NULL;
2233 client_send_control(req, header, &reply);
2236 static void control_db_attach_persistent(TALLOC_CTX *mem_ctx,
2237 struct tevent_req *req,
2238 struct ctdb_req_header *header,
2239 struct ctdb_req_control *request)
2241 struct client_state *state = tevent_req_data(
2242 req, struct client_state);
2243 struct ctdbd_context *ctdb = state->ctdb;
2244 struct ctdb_reply_control reply;
2245 struct database *db;
2247 reply.rdata.opcode = request->opcode;
2249 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
2250 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
2255 db = database_new(ctdb->db_map, request->rdata.data.db_name,
2256 CTDB_DB_FLAGS_PERSISTENT);
2259 reply.errmsg = "Failed to attach database";
2260 client_send_control(req, header, &reply);
2265 reply.rdata.data.db_id = db->id;
2267 reply.errmsg = NULL;
2268 client_send_control(req, header, &reply);
2271 static void control_uptime(TALLOC_CTX *mem_ctx,
2272 struct tevent_req *req,
2273 struct ctdb_req_header *header,
2274 struct ctdb_req_control *request)
2276 struct client_state *state = tevent_req_data(
2277 req, struct client_state);
2278 struct ctdbd_context *ctdb = state->ctdb;
2279 struct ctdb_reply_control reply;
2280 struct ctdb_uptime *uptime;;
2282 reply.rdata.opcode = request->opcode;
2284 uptime = talloc_zero(mem_ctx, struct ctdb_uptime);
2285 if (uptime == NULL) {
2289 uptime->current_time = tevent_timeval_current();
2290 uptime->ctdbd_start_time = ctdb->start_time;
2291 uptime->last_recovery_started = ctdb->recovery_start_time;
2292 uptime->last_recovery_finished = ctdb->recovery_end_time;
2294 reply.rdata.data.uptime = uptime;
2296 reply.errmsg = NULL;
2297 client_send_control(req, header, &reply);
2302 reply.errmsg = "Memory error";
2303 client_send_control(req, header, &reply);
2306 static void control_reload_nodes_file(TALLOC_CTX *mem_ctx,
2307 struct tevent_req *req,
2308 struct ctdb_req_header *header,
2309 struct ctdb_req_control *request)
2311 struct client_state *state = tevent_req_data(
2312 req, struct client_state);
2313 struct ctdbd_context *ctdb = state->ctdb;
2314 struct ctdb_reply_control reply;
2315 struct ctdb_node_map *nodemap;
2316 struct node_map *node_map = ctdb->node_map;
2319 reply.rdata.opcode = request->opcode;
2321 nodemap = read_nodes_file(mem_ctx, header->destnode);
2322 if (nodemap == NULL) {
2326 for (i=0; i<nodemap->num; i++) {
2329 if (i < node_map->num_nodes &&
2330 ctdb_sock_addr_same(&nodemap->node[i].addr,
2331 &node_map->node[i].addr)) {
2335 if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
2338 node = &node_map->node[i];
2340 node->flags |= NODE_FLAGS_DELETED;
2341 ret = ctdb_sock_addr_from_string("0.0.0.0", &node->addr,
2344 /* Can't happen, but Coverity... */
2351 if (i < node_map->num_nodes &&
2352 node_map->node[i].flags & NODE_FLAGS_DELETED) {
2353 node = &node_map->node[i];
2355 node->flags &= ~NODE_FLAGS_DELETED;
2356 node->addr = nodemap->node[i].addr;
2361 node_map->node = talloc_realloc(node_map, node_map->node,
2363 node_map->num_nodes+1);
2364 if (node_map->node == NULL) {
2367 node = &node_map->node[node_map->num_nodes];
2369 node->addr = nodemap->node[i].addr;
2370 node->pnn = nodemap->node[i].pnn;
2372 node->capabilities = CTDB_CAP_DEFAULT;
2373 node->recovery_disabled = false;
2374 node->recovery_substate = NULL;
2376 node_map->num_nodes += 1;
2379 talloc_free(nodemap);
2382 reply.errmsg = NULL;
2383 client_send_control(req, header, &reply);
2388 reply.errmsg = "Memory error";
2389 client_send_control(req, header, &reply);
2392 static void control_get_capabilities(TALLOC_CTX *mem_ctx,
2393 struct tevent_req *req,
2394 struct ctdb_req_header *header,
2395 struct ctdb_req_control *request)
2397 struct client_state *state = tevent_req_data(
2398 req, struct client_state);
2399 struct ctdbd_context *ctdb = state->ctdb;
2400 struct ctdb_reply_control reply;
2404 reply.rdata.opcode = request->opcode;
2406 node = &ctdb->node_map->node[header->destnode];
2407 caps = node->capabilities;
2409 if (node->flags & NODE_FLAGS_FAKE_TIMEOUT) {
2410 /* Don't send reply */
2414 reply.rdata.data.caps = caps;
2416 reply.errmsg = NULL;
2418 client_send_control(req, header, &reply);
2421 static void control_release_ip(TALLOC_CTX *mem_ctx,
2422 struct tevent_req *req,
2423 struct ctdb_req_header *header,
2424 struct ctdb_req_control *request)
2426 struct client_state *state = tevent_req_data(
2427 req, struct client_state);
2428 struct ctdbd_context *ctdb = state->ctdb;
2429 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2430 struct ctdb_reply_control reply;
2431 struct ctdb_public_ip_list *ips = NULL;
2432 struct ctdb_public_ip *t = NULL;
2435 reply.rdata.opcode = request->opcode;
2437 if (ctdb->known_ips == NULL) {
2438 D_INFO("RELEASE_IP %s - not a public IP\n",
2439 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2443 ips = &ctdb->known_ips[header->destnode];
2446 for (i = 0; i < ips->num; i++) {
2447 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2453 D_INFO("RELEASE_IP %s - not a public IP\n",
2454 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2458 if (t->pnn != header->destnode) {
2459 if (header->destnode == ip->pnn) {
2460 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2461 ctdb_sock_addr_to_string(mem_ctx,
2465 reply.errmsg = "RELEASE_IP to TAKE_IP node";
2466 client_send_control(req, header, &reply);
2470 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2471 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2475 D_NOTICE("RELEASE_IP %s - to node %d\n",
2476 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2483 reply.errmsg = NULL;
2484 client_send_control(req, header, &reply);
2487 static void control_takeover_ip(TALLOC_CTX *mem_ctx,
2488 struct tevent_req *req,
2489 struct ctdb_req_header *header,
2490 struct ctdb_req_control *request)
2492 struct client_state *state = tevent_req_data(
2493 req, struct client_state);
2494 struct ctdbd_context *ctdb = state->ctdb;
2495 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2496 struct ctdb_reply_control reply;
2497 struct ctdb_public_ip_list *ips = NULL;
2498 struct ctdb_public_ip *t = NULL;
2501 reply.rdata.opcode = request->opcode;
2503 if (ctdb->known_ips == NULL) {
2504 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2505 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2509 ips = &ctdb->known_ips[header->destnode];
2512 for (i = 0; i < ips->num; i++) {
2513 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2519 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2520 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2524 if (t->pnn == header->destnode) {
2525 D_INFO("TAKEOVER_IP %s - redundant\n",
2526 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2528 D_NOTICE("TAKEOVER_IP %s\n",
2529 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2535 reply.errmsg = NULL;
2536 client_send_control(req, header, &reply);
2539 static void control_get_public_ips(TALLOC_CTX *mem_ctx,
2540 struct tevent_req *req,
2541 struct ctdb_req_header *header,
2542 struct ctdb_req_control *request)
2544 struct client_state *state = tevent_req_data(
2545 req, struct client_state);
2546 struct ctdbd_context *ctdb = state->ctdb;
2547 struct ctdb_reply_control reply;
2548 struct ctdb_public_ip_list *ips = NULL;
2550 reply.rdata.opcode = request->opcode;
2552 if (ctdb->known_ips == NULL) {
2553 /* No IPs defined so create a dummy empty struct and ship it */
2554 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2556 reply.status = ENOMEM;
2557 reply.errmsg = "Memory error";
2563 ips = &ctdb->known_ips[header->destnode];
2565 if (request->flags & CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE) {
2566 /* If runstate is not RUNNING or a node is then return
2567 * no available IPs. Don't worry about interface
2568 * states here - we're not faking down to that level.
2570 if (ctdb->runstate != CTDB_RUNSTATE_RUNNING) {
2571 /* No available IPs: return dummy empty struct */
2572 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2574 reply.status = ENOMEM;
2575 reply.errmsg = "Memory error";
2582 reply.rdata.data.pubip_list = ips;
2584 reply.errmsg = NULL;
2587 client_send_control(req, header, &reply);
2590 static void control_get_nodemap(TALLOC_CTX *mem_ctx,
2591 struct tevent_req *req,
2592 struct ctdb_req_header *header,
2593 struct ctdb_req_control *request)
2595 struct client_state *state = tevent_req_data(
2596 req, struct client_state);
2597 struct ctdbd_context *ctdb = state->ctdb;
2598 struct ctdb_reply_control reply;
2599 struct ctdb_node_map *nodemap;
2603 reply.rdata.opcode = request->opcode;
2605 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
2606 if (nodemap == NULL) {
2610 nodemap->num = ctdb->node_map->num_nodes;
2611 nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2613 if (nodemap->node == NULL) {
2617 for (i=0; i<nodemap->num; i++) {
2618 node = &ctdb->node_map->node[i];
2619 nodemap->node[i] = (struct ctdb_node_and_flags) {
2621 .flags = node->flags,
2626 reply.rdata.data.nodemap = nodemap;
2628 reply.errmsg = NULL;
2629 client_send_control(req, header, &reply);
2634 reply.errmsg = "Memory error";
2635 client_send_control(req, header, &reply);
2638 static void control_get_reclock_file(TALLOC_CTX *mem_ctx,
2639 struct tevent_req *req,
2640 struct ctdb_req_header *header,
2641 struct ctdb_req_control *request)
2643 struct client_state *state = tevent_req_data(
2644 req, struct client_state);
2645 struct ctdbd_context *ctdb = state->ctdb;
2646 struct ctdb_reply_control reply;
2648 reply.rdata.opcode = request->opcode;
2650 if (ctdb->reclock != NULL) {
2651 reply.rdata.data.reclock_file =
2652 talloc_strdup(mem_ctx, ctdb->reclock);
2653 if (reply.rdata.data.reclock_file == NULL) {
2654 reply.status = ENOMEM;
2655 reply.errmsg = "Memory error";
2659 reply.rdata.data.reclock_file = NULL;
2663 reply.errmsg = NULL;
2666 client_send_control(req, header, &reply);
2669 static void control_stop_node(TALLOC_CTX *mem_ctx,
2670 struct tevent_req *req,
2671 struct ctdb_req_header *header,
2672 struct ctdb_req_control *request)
2674 struct client_state *state = tevent_req_data(
2675 req, struct client_state);
2676 struct ctdbd_context *ctdb = state->ctdb;
2677 struct ctdb_reply_control reply;
2679 reply.rdata.opcode = request->opcode;
2681 DEBUG(DEBUG_INFO, ("Stopping node\n"));
2682 ctdb->node_map->node[header->destnode].flags |= NODE_FLAGS_STOPPED;
2685 reply.errmsg = NULL;
2687 client_send_control(req, header, &reply);
2691 static void control_continue_node(TALLOC_CTX *mem_ctx,
2692 struct tevent_req *req,
2693 struct ctdb_req_header *header,
2694 struct ctdb_req_control *request)
2696 struct client_state *state = tevent_req_data(
2697 req, struct client_state);
2698 struct ctdbd_context *ctdb = state->ctdb;
2699 struct ctdb_reply_control reply;
2701 reply.rdata.opcode = request->opcode;
2703 DEBUG(DEBUG_INFO, ("Continue node\n"));
2704 ctdb->node_map->node[header->destnode].flags &= ~NODE_FLAGS_STOPPED;
2707 reply.errmsg = NULL;
2709 client_send_control(req, header, &reply);
2713 static void set_ban_state_callback(struct tevent_req *subreq)
2715 struct node *node = tevent_req_callback_data(
2716 subreq, struct node);
2719 status = tevent_wakeup_recv(subreq);
2720 TALLOC_FREE(subreq);
2722 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2725 node->flags &= ~NODE_FLAGS_BANNED;
2728 static void control_set_ban_state(TALLOC_CTX *mem_ctx,
2729 struct tevent_req *req,
2730 struct ctdb_req_header *header,
2731 struct ctdb_req_control *request)
2733 struct client_state *state = tevent_req_data(
2734 req, struct client_state);
2735 struct tevent_req *subreq;
2736 struct ctdbd_context *ctdb = state->ctdb;
2737 struct ctdb_ban_state *ban = request->rdata.data.ban_state;
2738 struct ctdb_reply_control reply;
2741 reply.rdata.opcode = request->opcode;
2743 if (ban->pnn != header->destnode) {
2745 ("SET_BAN_STATE control for PNN %d rejected\n",
2747 reply.status = EINVAL;
2751 node = &ctdb->node_map->node[header->destnode];
2753 if (ban->time == 0) {
2754 DEBUG(DEBUG_INFO,("Unbanning this node\n"));
2755 node->flags &= ~NODE_FLAGS_BANNED;
2759 subreq = tevent_wakeup_send(ctdb->node_map, state->ev,
2760 tevent_timeval_current_ofs(
2762 if (subreq == NULL) {
2763 reply.status = ENOMEM;
2766 tevent_req_set_callback(subreq, set_ban_state_callback, node);
2768 DEBUG(DEBUG_INFO, ("Banning this node for %d seconds\n", ban->time));
2769 node->flags |= NODE_FLAGS_BANNED;
2770 ctdb->vnn_map->generation = INVALID_GENERATION;
2774 reply.errmsg = NULL;
2776 client_send_control(req, header, &reply);
2780 reply.errmsg = "Failed to ban node";
2783 static void control_get_db_seqnum(TALLOC_CTX *mem_ctx,
2784 struct tevent_req *req,
2785 struct ctdb_req_header *header,
2786 struct ctdb_req_control *request)
2788 struct client_state *state = tevent_req_data(
2789 req, struct client_state);
2790 struct ctdbd_context *ctdb = state->ctdb;
2791 struct ctdb_reply_control reply;
2792 struct database *db;
2795 reply.rdata.opcode = request->opcode;
2797 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2799 reply.status = ENOENT;
2800 reply.errmsg = "Database not found";
2804 ret = database_seqnum(db, &seqnum);
2806 reply.rdata.data.seqnum = seqnum;
2808 reply.errmsg = NULL;
2811 reply.errmsg = "Failed to get seqnum";
2815 client_send_control(req, header, &reply);
2818 static void control_db_get_health(TALLOC_CTX *mem_ctx,
2819 struct tevent_req *req,
2820 struct ctdb_req_header *header,
2821 struct ctdb_req_control *request)
2823 struct client_state *state = tevent_req_data(
2824 req, struct client_state);
2825 struct ctdbd_context *ctdb = state->ctdb;
2826 struct ctdb_reply_control reply;
2827 struct database *db;
2829 reply.rdata.opcode = request->opcode;
2831 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2833 reply.status = ENOENT;
2834 reply.errmsg = "Database not found";
2836 reply.rdata.data.reason = NULL;
2838 reply.errmsg = NULL;
2841 client_send_control(req, header, &reply);
2844 static struct ctdb_iface_list *get_ctdb_iface_list(TALLOC_CTX *mem_ctx,
2845 struct ctdbd_context *ctdb)
2847 struct ctdb_iface_list *iface_list;
2848 struct interface *iface;
2851 iface_list = talloc_zero(mem_ctx, struct ctdb_iface_list);
2852 if (iface_list == NULL) {
2856 iface_list->num = ctdb->iface_map->num;
2857 iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2859 if (iface_list->iface == NULL) {
2860 TALLOC_FREE(iface_list);
2864 for (i=0; i<iface_list->num; i++) {
2865 iface = &ctdb->iface_map->iface[i];
2866 iface_list->iface[i] = (struct ctdb_iface) {
2867 .link_state = iface->link_up,
2868 .references = iface->references,
2870 strlcpy(iface_list->iface[i].name, iface->name,
2871 sizeof(iface_list->iface[i].name));
2878 static void control_get_public_ip_info(TALLOC_CTX *mem_ctx,
2879 struct tevent_req *req,
2880 struct ctdb_req_header *header,
2881 struct ctdb_req_control *request)
2883 struct client_state *state = tevent_req_data(
2884 req, struct client_state);
2885 struct ctdbd_context *ctdb = state->ctdb;
2886 struct ctdb_reply_control reply;
2887 ctdb_sock_addr *addr = request->rdata.data.addr;
2888 struct ctdb_public_ip_list *known = NULL;
2889 struct ctdb_public_ip_info *info = NULL;
2892 reply.rdata.opcode = request->opcode;
2894 info = talloc_zero(mem_ctx, struct ctdb_public_ip_info);
2896 reply.status = ENOMEM;
2897 reply.errmsg = "Memory error";
2901 reply.rdata.data.ipinfo = info;
2903 if (ctdb->known_ips != NULL) {
2904 known = &ctdb->known_ips[header->destnode];
2906 /* No IPs defined so create a dummy empty struct and
2907 * fall through. The given IP won't be matched
2910 known = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2911 if (known == NULL) {
2912 reply.status = ENOMEM;
2913 reply.errmsg = "Memory error";
2918 for (i = 0; i < known->num; i++) {
2919 if (ctdb_sock_addr_same_ip(&known->ip[i].addr,
2925 if (i == known->num) {
2926 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
2927 ctdb_sock_addr_to_string(mem_ctx, addr, false));
2929 reply.errmsg = "Unknown address";
2933 info->ip = known->ip[i];
2935 /* The fake PUBLICIPS stanza and resulting known_ips data
2936 * don't know anything about interfaces, so completely fake
2939 info->active_idx = 0;
2941 info->ifaces = get_ctdb_iface_list(mem_ctx, ctdb);
2942 if (info->ifaces == NULL) {
2943 reply.status = ENOMEM;
2944 reply.errmsg = "Memory error";
2949 reply.errmsg = NULL;
2952 client_send_control(req, header, &reply);
2955 static void control_get_ifaces(TALLOC_CTX *mem_ctx,
2956 struct tevent_req *req,
2957 struct ctdb_req_header *header,
2958 struct ctdb_req_control *request)
2960 struct client_state *state = tevent_req_data(
2961 req, struct client_state);
2962 struct ctdbd_context *ctdb = state->ctdb;
2963 struct ctdb_reply_control reply;
2964 struct ctdb_iface_list *iface_list;
2966 reply.rdata.opcode = request->opcode;
2968 iface_list = get_ctdb_iface_list(mem_ctx, ctdb);
2969 if (iface_list == NULL) {
2973 reply.rdata.data.iface_list = iface_list;
2975 reply.errmsg = NULL;
2976 client_send_control(req, header, &reply);
2981 reply.errmsg = "Memory error";
2982 client_send_control(req, header, &reply);
2985 static void control_set_iface_link_state(TALLOC_CTX *mem_ctx,
2986 struct tevent_req *req,
2987 struct ctdb_req_header *header,
2988 struct ctdb_req_control *request)
2990 struct client_state *state = tevent_req_data(
2991 req, struct client_state);
2992 struct ctdbd_context *ctdb = state->ctdb;
2993 struct ctdb_reply_control reply;
2994 struct ctdb_iface *in_iface;
2995 struct interface *iface = NULL;
2996 bool link_up = false;
2999 reply.rdata.opcode = request->opcode;
3001 in_iface = request->rdata.data.iface;
3003 if (in_iface->name[CTDB_IFACE_SIZE] != '\0') {
3004 reply.errmsg = "interface name not terminated";
3008 switch (in_iface->link_state) {
3018 reply.errmsg = "invalid link state";
3022 if (in_iface->references != 0) {
3023 reply.errmsg = "references should be 0";
3027 for (i=0; i<ctdb->iface_map->num; i++) {
3028 if (strcmp(ctdb->iface_map->iface[i].name,
3029 in_iface->name) == 0) {
3030 iface = &ctdb->iface_map->iface[i];
3035 if (iface == NULL) {
3036 reply.errmsg = "interface not found";
3040 iface->link_up = link_up;
3043 reply.errmsg = NULL;
3044 client_send_control(req, header, &reply);
3049 client_send_control(req, header, &reply);
3052 static void control_set_db_readonly(TALLOC_CTX *mem_ctx,
3053 struct tevent_req *req,
3054 struct ctdb_req_header *header,
3055 struct ctdb_req_control *request)
3057 struct client_state *state = tevent_req_data(
3058 req, struct client_state);
3059 struct ctdbd_context *ctdb = state->ctdb;
3060 struct ctdb_reply_control reply;
3061 struct database *db;
3063 reply.rdata.opcode = request->opcode;
3065 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3067 reply.status = ENOENT;
3068 reply.errmsg = "Database not found";
3072 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3073 reply.status = EINVAL;
3074 reply.errmsg = "Can not set READONLY on persistent db";
3078 db->flags |= CTDB_DB_FLAGS_READONLY;
3080 reply.errmsg = NULL;
3083 client_send_control(req, header, &reply);
3086 static void control_set_db_sticky(TALLOC_CTX *mem_ctx,
3087 struct tevent_req *req,
3088 struct ctdb_req_header *header,
3089 struct ctdb_req_control *request)
3091 struct client_state *state = tevent_req_data(
3092 req, struct client_state);
3093 struct ctdbd_context *ctdb = state->ctdb;
3094 struct ctdb_reply_control reply;
3095 struct database *db;
3097 reply.rdata.opcode = request->opcode;
3099 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3101 reply.status = ENOENT;
3102 reply.errmsg = "Database not found";
3106 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3107 reply.status = EINVAL;
3108 reply.errmsg = "Can not set STICKY on persistent db";
3112 db->flags |= CTDB_DB_FLAGS_STICKY;
3114 reply.errmsg = NULL;
3117 client_send_control(req, header, &reply);
3120 static void control_ipreallocated(TALLOC_CTX *mem_ctx,
3121 struct tevent_req *req,
3122 struct ctdb_req_header *header,
3123 struct ctdb_req_control *request)
3125 struct ctdb_reply_control reply;
3127 /* Always succeed */
3128 reply.rdata.opcode = request->opcode;
3130 reply.errmsg = NULL;
3132 client_send_control(req, header, &reply);
3135 static void control_get_runstate(TALLOC_CTX *mem_ctx,
3136 struct tevent_req *req,
3137 struct ctdb_req_header *header,
3138 struct ctdb_req_control *request)
3140 struct client_state *state = tevent_req_data(
3141 req, struct client_state);
3142 struct ctdbd_context *ctdb = state->ctdb;
3143 struct ctdb_reply_control reply;
3145 reply.rdata.opcode = request->opcode;
3146 reply.rdata.data.runstate = ctdb->runstate;
3148 reply.errmsg = NULL;
3150 client_send_control(req, header, &reply);
3153 static void control_get_nodes_file(TALLOC_CTX *mem_ctx,
3154 struct tevent_req *req,
3155 struct ctdb_req_header *header,
3156 struct ctdb_req_control *request)
3158 struct ctdb_reply_control reply;
3159 struct ctdb_node_map *nodemap;
3161 reply.rdata.opcode = request->opcode;
3163 nodemap = read_nodes_file(mem_ctx, header->destnode);
3164 if (nodemap == NULL) {
3168 reply.rdata.data.nodemap = nodemap;
3170 reply.errmsg = NULL;
3171 client_send_control(req, header, &reply);
3176 reply.errmsg = "Failed to read nodes file";
3177 client_send_control(req, header, &reply);
3180 static void control_db_open_flags(TALLOC_CTX *mem_ctx,
3181 struct tevent_req *req,
3182 struct ctdb_req_header *header,
3183 struct ctdb_req_control *request)
3185 struct client_state *state = tevent_req_data(
3186 req, struct client_state);
3187 struct ctdbd_context *ctdb = state->ctdb;
3188 struct ctdb_reply_control reply;
3189 struct database *db;
3191 reply.rdata.opcode = request->opcode;
3193 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3195 reply.status = ENOENT;
3196 reply.errmsg = "Database not found";
3198 reply.rdata.data.tdb_flags = database_flags(db->flags);
3200 reply.errmsg = NULL;
3203 client_send_control(req, header, &reply);
3206 static void control_db_attach_replicated(TALLOC_CTX *mem_ctx,
3207 struct tevent_req *req,
3208 struct ctdb_req_header *header,
3209 struct ctdb_req_control *request)
3211 struct client_state *state = tevent_req_data(
3212 req, struct client_state);
3213 struct ctdbd_context *ctdb = state->ctdb;
3214 struct ctdb_reply_control reply;
3215 struct database *db;
3217 reply.rdata.opcode = request->opcode;
3219 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
3220 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
3225 db = database_new(ctdb->db_map, request->rdata.data.db_name,
3226 CTDB_DB_FLAGS_REPLICATED);
3229 reply.errmsg = "Failed to attach database";
3230 client_send_control(req, header, &reply);
3235 reply.rdata.data.db_id = db->id;
3237 reply.errmsg = NULL;
3238 client_send_control(req, header, &reply);
3241 static void control_check_pid_srvid(TALLOC_CTX *mem_ctx,
3242 struct tevent_req *req,
3243 struct ctdb_req_header *header,
3244 struct ctdb_req_control *request)
3246 struct client_state *state = tevent_req_data(
3247 req, struct client_state);
3248 struct ctdbd_context *ctdb = state->ctdb;
3249 struct ctdb_client *client;
3250 struct client_state *cstate;
3251 struct ctdb_reply_control reply;
3252 bool pid_found, srvid_found;
3255 reply.rdata.opcode = request->opcode;
3258 srvid_found = false;
3260 for (client=ctdb->client_list; client != NULL; client=client->next) {
3261 if (client->pid == request->rdata.data.pid_srvid->pid) {
3263 cstate = (struct client_state *)client->state;
3264 ret = srvid_exists(ctdb->srv,
3265 request->rdata.data.pid_srvid->srvid,
3269 ret = kill(cstate->pid, 0);
3272 reply.errmsg = strerror(errno);
3275 reply.errmsg = NULL;
3283 reply.errmsg = "No client for PID";
3284 } else if (! srvid_found) {
3286 reply.errmsg = "No client for PID and SRVID";
3289 client_send_control(req, header, &reply);
3292 static bool fake_control_failure(TALLOC_CTX *mem_ctx,
3293 struct tevent_req *req,
3294 struct ctdb_req_header *header,
3295 struct ctdb_req_control *request)
3297 struct client_state *state = tevent_req_data(
3298 req, struct client_state);
3299 struct ctdbd_context *ctdb = state->ctdb;
3300 struct ctdb_reply_control reply;
3301 struct fake_control_failure *f = NULL;
3303 D_DEBUG("Checking fake control failure for control %u on node %u\n",
3304 request->opcode, header->destnode);
3305 for (f = ctdb->control_failures; f != NULL; f = f->next) {
3306 if (f->opcode == request->opcode &&
3307 (f->pnn == header->destnode ||
3308 f->pnn == CTDB_UNKNOWN_PNN)) {
3310 reply.rdata.opcode = request->opcode;
3311 if (strcmp(f->error, "TIMEOUT") == 0) {
3312 /* Causes no reply */
3313 D_ERR("Control %u fake timeout on node %u\n",
3314 request->opcode, header->destnode);
3316 } else if (strcmp(f->error, "ERROR") == 0) {
3317 D_ERR("Control %u fake error on node %u\n",
3318 request->opcode, header->destnode);
3320 reply.errmsg = f->comment;
3321 client_send_control(req, header, &reply);
3330 static void control_error(TALLOC_CTX *mem_ctx,
3331 struct tevent_req *req,
3332 struct ctdb_req_header *header,
3333 struct ctdb_req_control *request)
3335 struct ctdb_reply_control reply;
3337 reply.rdata.opcode = request->opcode;
3339 reply.errmsg = "Not implemented";
3341 client_send_control(req, header, &reply);
3345 * Handling protocol - messages
3348 struct disable_recoveries_state {
3352 static void disable_recoveries_callback(struct tevent_req *subreq)
3354 struct disable_recoveries_state *substate = tevent_req_callback_data(
3355 subreq, struct disable_recoveries_state);
3358 status = tevent_wakeup_recv(subreq);
3359 TALLOC_FREE(subreq);
3361 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
3364 substate->node->recovery_disabled = false;
3365 TALLOC_FREE(substate->node->recovery_substate);
3368 static void message_disable_recoveries(TALLOC_CTX *mem_ctx,
3369 struct tevent_req *req,
3370 struct ctdb_req_header *header,
3371 struct ctdb_req_message *request)
3373 struct client_state *state = tevent_req_data(
3374 req, struct client_state);
3375 struct tevent_req *subreq;
3376 struct ctdbd_context *ctdb = state->ctdb;
3377 struct disable_recoveries_state *substate;
3378 struct ctdb_disable_message *disable = request->data.disable;
3379 struct ctdb_req_message_data reply;
3384 node = &ctdb->node_map->node[header->destnode];
3386 if (disable->timeout == 0) {
3387 TALLOC_FREE(node->recovery_substate);
3388 node->recovery_disabled = false;
3389 DEBUG(DEBUG_INFO, ("Enabled recoveries on node %u\n",
3394 substate = talloc_zero(ctdb->node_map,
3395 struct disable_recoveries_state);
3396 if (substate == NULL) {
3400 substate->node = node;
3402 subreq = tevent_wakeup_send(substate, state->ev,
3403 tevent_timeval_current_ofs(
3404 disable->timeout, 0));
3405 if (subreq == NULL) {
3406 talloc_free(substate);
3409 tevent_req_set_callback(subreq, disable_recoveries_callback, substate);
3411 DEBUG(DEBUG_INFO, ("Disabled recoveries for %d seconds on node %u\n",
3412 disable->timeout, header->destnode));
3413 node->recovery_substate = substate;
3414 node->recovery_disabled = true;
3417 ret = header->destnode;
3420 reply.srvid = disable->srvid;
3421 data.dptr = (uint8_t *)&ret;
3422 data.dsize = sizeof(int);
3425 client_send_message(req, header, &reply);
3428 static void message_takeover_run(TALLOC_CTX *mem_ctx,
3429 struct tevent_req *req,
3430 struct ctdb_req_header *header,
3431 struct ctdb_req_message *request)
3433 struct client_state *state = tevent_req_data(
3434 req, struct client_state);
3435 struct ctdbd_context *ctdb = state->ctdb;
3436 struct ctdb_srvid_message *srvid = request->data.msg;
3437 struct ctdb_req_message_data reply;
3441 if (header->destnode != ctdb->node_map->recmaster) {
3442 /* No reply! Only recmaster replies... */
3446 DEBUG(DEBUG_INFO, ("IP takover run on node %u\n",
3448 ret = header->destnode;
3450 reply.srvid = srvid->srvid;
3451 data.dptr = (uint8_t *)&ret;
3452 data.dsize = sizeof(int);
3455 client_send_message(req, header, &reply);
3459 * Handle a single client
3462 static void client_read_handler(uint8_t *buf, size_t buflen,
3463 void *private_data);
3464 static void client_dead_handler(void *private_data);
3465 static void client_process_packet(struct tevent_req *req,
3466 uint8_t *buf, size_t buflen);
3467 static void client_process_call(struct tevent_req *req,
3468 uint8_t *buf, size_t buflen);
3469 static void client_process_message(struct tevent_req *req,
3470 uint8_t *buf, size_t buflen);
3471 static void client_process_control(struct tevent_req *req,
3472 uint8_t *buf, size_t buflen);
3473 static void client_reply_done(struct tevent_req *subreq);
3475 static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
3476 struct tevent_context *ev,
3477 int fd, struct ctdbd_context *ctdb,
3480 struct tevent_req *req;
3481 struct client_state *state;
3483 socklen_t crl = sizeof(struct ucred);
3486 req = tevent_req_create(mem_ctx, &state, struct client_state);
3496 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
3498 tevent_req_error(req, ret);
3499 return tevent_req_post(req, ev);
3501 state->pid = cr.pid;
3503 ret = comm_setup(state, ev, fd, client_read_handler, req,
3504 client_dead_handler, req, &state->comm);
3506 tevent_req_error(req, ret);
3507 return tevent_req_post(req, ev);
3510 ret = client_add(ctdb, state->pid, state);
3512 tevent_req_error(req, ret);
3513 return tevent_req_post(req, ev);
3516 DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
3521 static void client_read_handler(uint8_t *buf, size_t buflen,
3524 struct tevent_req *req = talloc_get_type_abort(
3525 private_data, struct tevent_req);
3526 struct client_state *state = tevent_req_data(
3527 req, struct client_state);
3528 struct ctdbd_context *ctdb = state->ctdb;
3529 struct ctdb_req_header header;
3533 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3538 if (buflen != header.length) {
3542 ret = ctdb_req_header_verify(&header, 0);
3547 header_fix_pnn(&header, ctdb);
3549 if (header.destnode == CTDB_BROADCAST_ALL) {
3550 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3551 header.destnode = i;
3553 ctdb_req_header_push(&header, buf, &np);
3554 client_process_packet(req, buf, buflen);
3559 if (header.destnode == CTDB_BROADCAST_CONNECTED) {
3560 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3561 if (ctdb->node_map->node[i].flags &
3562 NODE_FLAGS_DISCONNECTED) {
3566 header.destnode = i;
3568 ctdb_req_header_push(&header, buf, &np);
3569 client_process_packet(req, buf, buflen);
3574 if (header.destnode > ctdb->node_map->num_nodes) {
3575 fprintf(stderr, "Invalid destination pnn 0x%x\n",
3581 if (ctdb->node_map->node[header.destnode].flags & NODE_FLAGS_DISCONNECTED) {
3582 fprintf(stderr, "Packet for disconnected node pnn %u\n",
3587 ctdb_req_header_push(&header, buf, &np);
3588 client_process_packet(req, buf, buflen);
3591 static void client_dead_handler(void *private_data)
3593 struct tevent_req *req = talloc_get_type_abort(
3594 private_data, struct tevent_req);
3596 tevent_req_done(req);
3599 static void client_process_packet(struct tevent_req *req,
3600 uint8_t *buf, size_t buflen)
3602 struct ctdb_req_header header;
3606 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3611 switch (header.operation) {
3613 client_process_call(req, buf, buflen);
3616 case CTDB_REQ_MESSAGE:
3617 client_process_message(req, buf, buflen);
3620 case CTDB_REQ_CONTROL:
3621 client_process_control(req, buf, buflen);
3629 static void client_process_call(struct tevent_req *req,
3630 uint8_t *buf, size_t buflen)
3632 struct client_state *state = tevent_req_data(
3633 req, struct client_state);
3634 struct ctdbd_context *ctdb = state->ctdb;
3635 TALLOC_CTX *mem_ctx;
3636 struct ctdb_req_header header;
3637 struct ctdb_req_call request;
3638 struct ctdb_reply_call reply;
3639 struct database *db;
3640 struct ctdb_ltdb_header hdr;
3644 mem_ctx = talloc_new(state);
3645 if (tevent_req_nomem(mem_ctx, req)) {
3649 ret = ctdb_req_call_pull(buf, buflen, &header, mem_ctx, &request);
3651 talloc_free(mem_ctx);
3652 tevent_req_error(req, ret);
3656 header_fix_pnn(&header, ctdb);
3658 if (header.destnode >= ctdb->node_map->num_nodes) {
3662 DEBUG(DEBUG_INFO, ("call db_id = %u\n", request.db_id));
3664 db = database_find(ctdb->db_map, request.db_id);
3669 ret = ltdb_fetch(db, request.key, &hdr, mem_ctx, &data);
3674 /* Fake migration */
3675 if (hdr.dmaster != ctdb->node_map->pnn) {
3676 hdr.dmaster = ctdb->node_map->pnn;
3678 ret = ltdb_store(db, request.key, &hdr, data);
3684 talloc_free(mem_ctx);
3687 reply.data = tdb_null;
3689 client_send_call(req, &header, &reply);
3693 talloc_free(mem_ctx);
3695 reply.data = tdb_null;
3697 client_send_call(req, &header, &reply);
3700 static void client_process_message(struct tevent_req *req,
3701 uint8_t *buf, size_t buflen)
3703 struct client_state *state = tevent_req_data(
3704 req, struct client_state);
3705 struct ctdbd_context *ctdb = state->ctdb;
3706 TALLOC_CTX *mem_ctx;
3707 struct ctdb_req_header header;
3708 struct ctdb_req_message request;
3712 mem_ctx = talloc_new(state);
3713 if (tevent_req_nomem(mem_ctx, req)) {
3717 ret = ctdb_req_message_pull(buf, buflen, &header, mem_ctx, &request);
3719 talloc_free(mem_ctx);
3720 tevent_req_error(req, ret);
3724 header_fix_pnn(&header, ctdb);
3726 if (header.destnode >= ctdb->node_map->num_nodes) {
3727 /* Many messages are not replied to, so just behave as
3728 * though this message was not received */
3729 fprintf(stderr, "Invalid node %d\n", header.destnode);
3730 talloc_free(mem_ctx);
3734 srvid = request.srvid;
3735 DEBUG(DEBUG_INFO, ("request srvid = 0x%"PRIx64"\n", srvid));
3737 if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
3738 message_disable_recoveries(mem_ctx, req, &header, &request);
3739 } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
3740 message_takeover_run(mem_ctx, req, &header, &request);
3744 talloc_free(mem_ctx);
3747 static void client_process_control(struct tevent_req *req,
3748 uint8_t *buf, size_t buflen)
3750 struct client_state *state = tevent_req_data(
3751 req, struct client_state);
3752 struct ctdbd_context *ctdb = state->ctdb;
3753 TALLOC_CTX *mem_ctx;
3754 struct ctdb_req_header header;
3755 struct ctdb_req_control request;
3758 mem_ctx = talloc_new(state);
3759 if (tevent_req_nomem(mem_ctx, req)) {
3763 ret = ctdb_req_control_pull(buf, buflen, &header, mem_ctx, &request);
3765 talloc_free(mem_ctx);
3766 tevent_req_error(req, ret);
3770 header_fix_pnn(&header, ctdb);
3772 if (header.destnode >= ctdb->node_map->num_nodes) {
3773 struct ctdb_reply_control reply;
3775 reply.rdata.opcode = request.opcode;
3776 reply.errmsg = "Invalid node";
3778 client_send_control(req, &header, &reply);
3782 DEBUG(DEBUG_INFO, ("request opcode = %u, reqid = %u\n",
3783 request.opcode, header.reqid));
3785 if (fake_control_failure(mem_ctx, req, &header, &request)) {
3789 switch (request.opcode) {
3790 case CTDB_CONTROL_PROCESS_EXISTS:
3791 control_process_exists(mem_ctx, req, &header, &request);
3794 case CTDB_CONTROL_PING:
3795 control_ping(mem_ctx, req, &header, &request);
3798 case CTDB_CONTROL_GETDBPATH:
3799 control_getdbpath(mem_ctx, req, &header, &request);
3802 case CTDB_CONTROL_GETVNNMAP:
3803 control_getvnnmap(mem_ctx, req, &header, &request);
3806 case CTDB_CONTROL_GET_DEBUG:
3807 control_get_debug(mem_ctx, req, &header, &request);
3810 case CTDB_CONTROL_SET_DEBUG:
3811 control_set_debug(mem_ctx, req, &header, &request);
3814 case CTDB_CONTROL_GET_DBMAP:
3815 control_get_dbmap(mem_ctx, req, &header, &request);
3818 case CTDB_CONTROL_GET_RECMODE:
3819 control_get_recmode(mem_ctx, req, &header, &request);
3822 case CTDB_CONTROL_SET_RECMODE:
3823 control_set_recmode(mem_ctx, req, &header, &request);
3826 case CTDB_CONTROL_DB_ATTACH:
3827 control_db_attach(mem_ctx, req, &header, &request);
3830 case CTDB_CONTROL_REGISTER_SRVID:
3831 control_register_srvid(mem_ctx, req, &header, &request);
3834 case CTDB_CONTROL_DEREGISTER_SRVID:
3835 control_deregister_srvid(mem_ctx, req, &header, &request);
3838 case CTDB_CONTROL_GET_DBNAME:
3839 control_get_dbname(mem_ctx, req, &header, &request);
3842 case CTDB_CONTROL_GET_PID:
3843 control_get_pid(mem_ctx, req, &header, &request);
3846 case CTDB_CONTROL_GET_RECMASTER:
3847 control_get_recmaster(mem_ctx, req, &header, &request);
3850 case CTDB_CONTROL_GET_PNN:
3851 control_get_pnn(mem_ctx, req, &header, &request);
3854 case CTDB_CONTROL_SHUTDOWN:
3855 control_shutdown(mem_ctx, req, &header, &request);
3858 case CTDB_CONTROL_SET_TUNABLE:
3859 control_set_tunable(mem_ctx, req, &header, &request);
3862 case CTDB_CONTROL_GET_TUNABLE:
3863 control_get_tunable(mem_ctx, req, &header, &request);
3866 case CTDB_CONTROL_LIST_TUNABLES:
3867 control_list_tunables(mem_ctx, req, &header, &request);
3870 case CTDB_CONTROL_MODIFY_FLAGS:
3871 control_modify_flags(mem_ctx, req, &header, &request);
3874 case CTDB_CONTROL_GET_ALL_TUNABLES:
3875 control_get_all_tunables(mem_ctx, req, &header, &request);
3878 case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
3879 control_db_attach_persistent(mem_ctx, req, &header, &request);
3882 case CTDB_CONTROL_UPTIME:
3883 control_uptime(mem_ctx, req, &header, &request);
3886 case CTDB_CONTROL_RELOAD_NODES_FILE:
3887 control_reload_nodes_file(mem_ctx, req, &header, &request);
3890 case CTDB_CONTROL_GET_CAPABILITIES:
3891 control_get_capabilities(mem_ctx, req, &header, &request);
3894 case CTDB_CONTROL_RELEASE_IP:
3895 control_release_ip(mem_ctx, req, &header, &request);
3898 case CTDB_CONTROL_TAKEOVER_IP:
3899 control_takeover_ip(mem_ctx, req, &header, &request);
3902 case CTDB_CONTROL_GET_PUBLIC_IPS:
3903 control_get_public_ips(mem_ctx, req, &header, &request);
3906 case CTDB_CONTROL_GET_NODEMAP:
3907 control_get_nodemap(mem_ctx, req, &header, &request);
3910 case CTDB_CONTROL_GET_RECLOCK_FILE:
3911 control_get_reclock_file(mem_ctx, req, &header, &request);
3914 case CTDB_CONTROL_STOP_NODE:
3915 control_stop_node(mem_ctx, req, &header, &request);
3918 case CTDB_CONTROL_CONTINUE_NODE:
3919 control_continue_node(mem_ctx, req, &header, &request);
3922 case CTDB_CONTROL_SET_BAN_STATE:
3923 control_set_ban_state(mem_ctx, req, &header, &request);
3926 case CTDB_CONTROL_GET_DB_SEQNUM:
3927 control_get_db_seqnum(mem_ctx, req, &header, &request);
3930 case CTDB_CONTROL_DB_GET_HEALTH:
3931 control_db_get_health(mem_ctx, req, &header, &request);
3934 case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
3935 control_get_public_ip_info(mem_ctx, req, &header, &request);
3938 case CTDB_CONTROL_GET_IFACES:
3939 control_get_ifaces(mem_ctx, req, &header, &request);
3942 case CTDB_CONTROL_SET_IFACE_LINK_STATE:
3943 control_set_iface_link_state(mem_ctx, req, &header, &request);
3946 case CTDB_CONTROL_SET_DB_READONLY:
3947 control_set_db_readonly(mem_ctx, req, &header, &request);
3950 case CTDB_CONTROL_SET_DB_STICKY:
3951 control_set_db_sticky(mem_ctx, req, &header, &request);
3954 case CTDB_CONTROL_IPREALLOCATED:
3955 control_ipreallocated(mem_ctx, req, &header, &request);
3958 case CTDB_CONTROL_GET_RUNSTATE:
3959 control_get_runstate(mem_ctx, req, &header, &request);
3962 case CTDB_CONTROL_GET_NODES_FILE:
3963 control_get_nodes_file(mem_ctx, req, &header, &request);
3966 case CTDB_CONTROL_DB_OPEN_FLAGS:
3967 control_db_open_flags(mem_ctx, req, &header, &request);
3970 case CTDB_CONTROL_DB_ATTACH_REPLICATED:
3971 control_db_attach_replicated(mem_ctx, req, &header, &request);
3974 case CTDB_CONTROL_CHECK_PID_SRVID:
3975 control_check_pid_srvid(mem_ctx, req, &header, &request);
3979 if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) {
3980 control_error(mem_ctx, req, &header, &request);
3986 talloc_free(mem_ctx);
3989 static int client_recv(struct tevent_req *req, int *perr)
3991 struct client_state *state = tevent_req_data(
3992 req, struct client_state);
3995 DEBUG(DEBUG_INFO, ("Client done fd=%d\n", state->fd));
3998 if (tevent_req_is_unix_error(req, &err)) {
4005 return state->status;
4012 struct server_state {
4013 struct tevent_context *ev;
4014 struct ctdbd_context *ctdb;
4018 static void server_new_client(struct tevent_req *subreq);
4019 static void server_client_done(struct tevent_req *subreq);
4021 static struct tevent_req *server_send(TALLOC_CTX *mem_ctx,
4022 struct tevent_context *ev,
4023 struct ctdbd_context *ctdb,
4026 struct tevent_req *req, *subreq;
4027 struct server_state *state;
4029 req = tevent_req_create(mem_ctx, &state, struct server_state);
4038 subreq = accept_send(state, ev, fd);
4039 if (tevent_req_nomem(subreq, req)) {
4040 return tevent_req_post(req, ev);
4042 tevent_req_set_callback(subreq, server_new_client, req);
4047 static void server_new_client(struct tevent_req *subreq)
4049 struct tevent_req *req = tevent_req_callback_data(
4050 subreq, struct tevent_req);
4051 struct server_state *state = tevent_req_data(
4052 req, struct server_state);
4053 struct ctdbd_context *ctdb = state->ctdb;
4057 client_fd = accept_recv(subreq, NULL, NULL, &ret);
4058 TALLOC_FREE(subreq);
4059 if (client_fd == -1) {
4060 tevent_req_error(req, ret);
4064 subreq = client_send(state, state->ev, client_fd,
4065 ctdb, ctdb->node_map->pnn);
4066 if (tevent_req_nomem(subreq, req)) {
4069 tevent_req_set_callback(subreq, server_client_done, req);
4071 ctdb->num_clients += 1;
4073 subreq = accept_send(state, state->ev, state->fd);
4074 if (tevent_req_nomem(subreq, req)) {
4077 tevent_req_set_callback(subreq, server_new_client, req);
4080 static void server_client_done(struct tevent_req *subreq)
4082 struct tevent_req *req = tevent_req_callback_data(
4083 subreq, struct tevent_req);
4084 struct server_state *state = tevent_req_data(
4085 req, struct server_state);
4086 struct ctdbd_context *ctdb = state->ctdb;
4090 status = client_recv(subreq, &ret);
4091 TALLOC_FREE(subreq);
4093 tevent_req_error(req, ret);
4097 ctdb->num_clients -= 1;
4100 /* Special status, to shutdown server */
4101 DEBUG(DEBUG_INFO, ("Shutting down server\n"));
4102 tevent_req_done(req);
4106 static bool server_recv(struct tevent_req *req, int *perr)
4110 if (tevent_req_is_unix_error(req, &err)) {
4123 static int socket_init(const char *sockpath)
4125 struct sockaddr_un addr;
4129 memset(&addr, 0, sizeof(addr));
4130 addr.sun_family = AF_UNIX;
4132 len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
4133 if (len >= sizeof(addr.sun_path)) {
4134 fprintf(stderr, "path too long: %s\n", sockpath);
4138 fd = socket(AF_UNIX, SOCK_STREAM, 0);
4140 fprintf(stderr, "socket failed - %s\n", sockpath);
4144 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
4146 fprintf(stderr, "bind failed - %s\n", sockpath);
4150 ret = listen(fd, 10);
4152 fprintf(stderr, "listen failed\n");
4156 DEBUG(DEBUG_INFO, ("Socket init done\n"));
4167 static struct options {
4169 const char *sockpath;
4170 const char *pidfile;
4171 const char *debuglevel;
4174 static struct poptOption cmdline_options[] = {
4176 { "dbdir", 'D', POPT_ARG_STRING, &options.dbdir, 0,
4177 "Database directory", "directory" },
4178 { "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
4179 "Unix domain socket path", "filename" },
4180 { "pidfile", 'p', POPT_ARG_STRING, &options.pidfile, 0,
4181 "pid file", "filename" } ,
4182 { "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
4183 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
4187 static void cleanup(void)
4189 unlink(options.sockpath);
4190 unlink(options.pidfile);
4193 static void signal_handler(int sig)
4199 static void start_server(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
4200 struct ctdbd_context *ctdb, int fd, int pfd)
4202 struct tevent_req *req;
4207 signal(SIGTERM, signal_handler);
4209 req = server_send(mem_ctx, ev, ctdb, fd);
4211 fprintf(stderr, "Memory error\n");
4215 len = write(pfd, &ret, sizeof(ret));
4216 if (len != sizeof(ret)) {
4217 fprintf(stderr, "Failed to send message to parent\n");
4222 tevent_req_poll(req, ev);
4224 server_recv(req, &ret);
4230 int main(int argc, const char *argv[])
4232 TALLOC_CTX *mem_ctx;
4233 struct ctdbd_context *ctdb;
4234 struct tevent_context *ev;
4236 int opt, fd, ret, pfd[2];
4241 pc = poptGetContext(argv[0], argc, argv, cmdline_options,
4242 POPT_CONTEXT_KEEP_FIRST);
4243 while ((opt = poptGetNextOpt(pc)) != -1) {
4244 fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
4248 if (options.dbdir == NULL) {
4249 fprintf(stderr, "Please specify database directory\n");
4250 poptPrintHelp(pc, stdout, 0);
4254 if (options.sockpath == NULL) {
4255 fprintf(stderr, "Please specify socket path\n");
4256 poptPrintHelp(pc, stdout, 0);
4260 if (options.pidfile == NULL) {
4261 fprintf(stderr, "Please specify pid file\n");
4262 poptPrintHelp(pc, stdout, 0);
4266 mem_ctx = talloc_new(NULL);
4267 if (mem_ctx == NULL) {
4268 fprintf(stderr, "Memory error\n");
4272 ret = logging_init(mem_ctx, "file:", options.debuglevel, "fake-ctdbd");
4274 fprintf(stderr, "Invalid debug level\n");
4275 poptPrintHelp(pc, stdout, 0);
4279 ctdb = ctdbd_setup(mem_ctx, options.dbdir);
4284 if (! ctdbd_verify(ctdb)) {
4288 ev = tevent_context_init(mem_ctx);
4290 fprintf(stderr, "Memory error\n");
4294 fd = socket_init(options.sockpath);
4301 fprintf(stderr, "Failed to create pipe\n");
4308 fprintf(stderr, "Failed to fork\n");
4316 start_server(mem_ctx, ev, ctdb, fd, pfd[1]);
4323 len = read(pfd[0], &ret, sizeof(ret));
4325 if (len != sizeof(ret)) {
4326 fprintf(stderr, "len = %zi\n", len);
4327 fprintf(stderr, "Failed to get message from child\n");
4332 fp = fopen(options.pidfile, "w");
4334 fprintf(stderr, "Failed to open pid file %s\n",
4339 fprintf(fp, "%d\n", pid);