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_control(
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_CONTROL,
1420 .destnode = header->srcnode,
1421 .srcnode = header->destnode,
1422 .reqid = header->reqid,
1425 return reply_header;
1428 static struct ctdb_req_header header_reply_message(
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_REQ_MESSAGE,
1439 .destnode = header->srcnode,
1440 .srcnode = header->destnode,
1444 return reply_header;
1451 struct client_state {
1452 struct tevent_context *ev;
1454 struct ctdbd_context *ctdb;
1457 struct comm_context *comm;
1458 struct srvid_register_state *rstate;
1463 * Send replies to controls and messages
1466 static void client_reply_done(struct tevent_req *subreq);
1468 static void client_send_message(struct tevent_req *req,
1469 struct ctdb_req_header *header,
1470 struct ctdb_req_message_data *message)
1472 struct client_state *state = tevent_req_data(
1473 req, struct client_state);
1474 struct ctdbd_context *ctdb = state->ctdb;
1475 struct tevent_req *subreq;
1476 struct ctdb_req_header reply_header;
1478 size_t datalen, buflen;
1481 reply_header = header_reply_message(header, ctdb);
1483 datalen = ctdb_req_message_data_len(&reply_header, message);
1484 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1486 tevent_req_error(req, ret);
1490 ret = ctdb_req_message_data_push(&reply_header, message,
1493 tevent_req_error(req, ret);
1497 DEBUG(DEBUG_INFO, ("message srvid = 0x%"PRIx64"\n", message->srvid));
1499 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1500 if (tevent_req_nomem(subreq, req)) {
1503 tevent_req_set_callback(subreq, client_reply_done, req);
1505 talloc_steal(subreq, buf);
1508 static void client_send_control(struct tevent_req *req,
1509 struct ctdb_req_header *header,
1510 struct ctdb_reply_control *reply)
1512 struct client_state *state = tevent_req_data(
1513 req, struct client_state);
1514 struct ctdbd_context *ctdb = state->ctdb;
1515 struct tevent_req *subreq;
1516 struct ctdb_req_header reply_header;
1518 size_t datalen, buflen;
1521 reply_header = header_reply_control(header, ctdb);
1523 datalen = ctdb_reply_control_len(&reply_header, reply);
1524 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
1526 tevent_req_error(req, ret);
1530 ret = ctdb_reply_control_push(&reply_header, reply, buf, &buflen);
1532 tevent_req_error(req, ret);
1536 DEBUG(DEBUG_INFO, ("reply opcode = %u\n", reply->rdata.opcode));
1538 subreq = comm_write_send(state, state->ev, state->comm, buf, buflen);
1539 if (tevent_req_nomem(subreq, req)) {
1542 tevent_req_set_callback(subreq, client_reply_done, req);
1544 talloc_steal(subreq, buf);
1547 static void client_reply_done(struct tevent_req *subreq)
1549 struct tevent_req *req = tevent_req_callback_data(
1550 subreq, struct tevent_req);
1554 status = comm_write_recv(subreq, &ret);
1555 TALLOC_FREE(subreq);
1557 tevent_req_error(req, ret);
1562 * Handling protocol - controls
1565 static void control_process_exists(TALLOC_CTX *mem_ctx,
1566 struct tevent_req *req,
1567 struct ctdb_req_header *header,
1568 struct ctdb_req_control *request)
1570 struct client_state *state = tevent_req_data(
1571 req, struct client_state);
1572 struct ctdbd_context *ctdb = state->ctdb;
1573 struct client_state *cstate;
1574 struct ctdb_reply_control reply;
1576 reply.rdata.opcode = request->opcode;
1578 cstate = client_find(ctdb, request->rdata.data.pid);
1579 if (cstate == NULL) {
1581 reply.errmsg = "No client for PID";
1583 reply.status = kill(request->rdata.data.pid, 0);
1584 reply.errmsg = NULL;
1587 client_send_control(req, header, &reply);
1590 static void control_ping(TALLOC_CTX *mem_ctx,
1591 struct tevent_req *req,
1592 struct ctdb_req_header *header,
1593 struct ctdb_req_control *request)
1595 struct client_state *state = tevent_req_data(
1596 req, struct client_state);
1597 struct ctdbd_context *ctdb = state->ctdb;
1598 struct ctdb_reply_control reply;
1600 reply.rdata.opcode = request->opcode;
1601 reply.status = ctdb->num_clients;
1602 reply.errmsg = NULL;
1604 client_send_control(req, header, &reply);
1607 static void control_getdbpath(TALLOC_CTX *mem_ctx,
1608 struct tevent_req *req,
1609 struct ctdb_req_header *header,
1610 struct ctdb_req_control *request)
1612 struct client_state *state = tevent_req_data(
1613 req, struct client_state);
1614 struct ctdbd_context *ctdb = state->ctdb;
1615 struct ctdb_reply_control reply;
1616 struct database *db;
1618 reply.rdata.opcode = request->opcode;
1620 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1622 reply.status = ENOENT;
1623 reply.errmsg = "Database not found";
1625 reply.rdata.data.db_path =
1626 talloc_strdup(mem_ctx, db->path);
1627 if (reply.rdata.data.db_path == NULL) {
1628 reply.status = ENOMEM;
1629 reply.errmsg = "Memory error";
1632 reply.errmsg = NULL;
1636 client_send_control(req, header, &reply);
1639 static void control_getvnnmap(TALLOC_CTX *mem_ctx,
1640 struct tevent_req *req,
1641 struct ctdb_req_header *header,
1642 struct ctdb_req_control *request)
1644 struct client_state *state = tevent_req_data(
1645 req, struct client_state);
1646 struct ctdbd_context *ctdb = state->ctdb;
1647 struct ctdb_reply_control reply;
1648 struct ctdb_vnn_map *vnnmap;
1650 reply.rdata.opcode = request->opcode;
1652 vnnmap = talloc_zero(mem_ctx, struct ctdb_vnn_map);
1653 if (vnnmap == NULL) {
1654 reply.status = ENOMEM;
1655 reply.errmsg = "Memory error";
1657 vnnmap->generation = ctdb->vnn_map->generation;
1658 vnnmap->size = ctdb->vnn_map->size;
1659 vnnmap->map = ctdb->vnn_map->map;
1661 reply.rdata.data.vnnmap = vnnmap;
1663 reply.errmsg = NULL;
1666 client_send_control(req, header, &reply);
1669 static void control_get_debug(TALLOC_CTX *mem_ctx,
1670 struct tevent_req *req,
1671 struct ctdb_req_header *header,
1672 struct ctdb_req_control *request)
1674 struct client_state *state = tevent_req_data(
1675 req, struct client_state);
1676 struct ctdbd_context *ctdb = state->ctdb;
1677 struct ctdb_reply_control reply;
1679 reply.rdata.opcode = request->opcode;
1680 reply.rdata.data.loglevel = (uint32_t)ctdb->log_level;
1682 reply.errmsg = NULL;
1684 client_send_control(req, header, &reply);
1687 static void control_set_debug(TALLOC_CTX *mem_ctx,
1688 struct tevent_req *req,
1689 struct ctdb_req_header *header,
1690 struct ctdb_req_control *request)
1692 struct client_state *state = tevent_req_data(
1693 req, struct client_state);
1694 struct ctdbd_context *ctdb = state->ctdb;
1695 struct ctdb_reply_control reply;
1697 ctdb->log_level = (int)request->rdata.data.loglevel;
1699 reply.rdata.opcode = request->opcode;
1701 reply.errmsg = NULL;
1703 client_send_control(req, header, &reply);
1706 static void control_get_dbmap(TALLOC_CTX *mem_ctx,
1707 struct tevent_req *req,
1708 struct ctdb_req_header *header,
1709 struct ctdb_req_control *request)
1711 struct client_state *state = tevent_req_data(
1712 req, struct client_state);
1713 struct ctdbd_context *ctdb = state->ctdb;
1714 struct ctdb_reply_control reply;
1715 struct ctdb_dbid_map *dbmap;
1716 struct database *db;
1719 reply.rdata.opcode = request->opcode;
1721 dbmap = talloc_zero(mem_ctx, struct ctdb_dbid_map);
1722 if (dbmap == NULL) {
1726 dbmap->num = database_count(ctdb->db_map);
1727 dbmap->dbs = talloc_zero_array(dbmap, struct ctdb_dbid, dbmap->num);
1728 if (dbmap->dbs == NULL) {
1732 db = ctdb->db_map->db;
1733 for (i = 0; i < dbmap->num; i++) {
1734 dbmap->dbs[i] = (struct ctdb_dbid) {
1742 reply.rdata.data.dbmap = dbmap;
1744 reply.errmsg = NULL;
1745 client_send_control(req, header, &reply);
1750 reply.errmsg = "Memory error";
1751 client_send_control(req, header, &reply);
1754 static void control_get_recmode(TALLOC_CTX *mem_ctx,
1755 struct tevent_req *req,
1756 struct ctdb_req_header *header,
1757 struct ctdb_req_control *request)
1759 struct client_state *state = tevent_req_data(
1760 req, struct client_state);
1761 struct ctdbd_context *ctdb = state->ctdb;
1762 struct ctdb_reply_control reply;
1764 reply.rdata.opcode = request->opcode;
1765 reply.status = ctdb->vnn_map->recmode;
1766 reply.errmsg = NULL;
1768 client_send_control(req, header, &reply);
1771 struct set_recmode_state {
1772 struct tevent_req *req;
1773 struct ctdbd_context *ctdb;
1774 struct ctdb_req_header header;
1775 struct ctdb_reply_control reply;
1778 static void set_recmode_callback(struct tevent_req *subreq)
1780 struct set_recmode_state *substate = tevent_req_callback_data(
1781 subreq, struct set_recmode_state);
1785 status = recover_recv(subreq, &ret);
1786 TALLOC_FREE(subreq);
1788 substate->reply.status = ret;
1789 substate->reply.errmsg = "recovery failed";
1791 substate->reply.status = 0;
1792 substate->reply.errmsg = NULL;
1795 client_send_control(substate->req, &substate->header, &substate->reply);
1796 talloc_free(substate);
1799 static void control_set_recmode(TALLOC_CTX *mem_ctx,
1800 struct tevent_req *req,
1801 struct ctdb_req_header *header,
1802 struct ctdb_req_control *request)
1804 struct client_state *state = tevent_req_data(
1805 req, struct client_state);
1806 struct tevent_req *subreq;
1807 struct ctdbd_context *ctdb = state->ctdb;
1808 struct set_recmode_state *substate;
1809 struct ctdb_reply_control reply;
1811 reply.rdata.opcode = request->opcode;
1813 if (request->rdata.data.recmode == CTDB_RECOVERY_NORMAL) {
1815 reply.errmsg = "Client cannot set recmode to NORMAL";
1819 substate = talloc_zero(ctdb, struct set_recmode_state);
1820 if (substate == NULL) {
1822 reply.errmsg = "Memory error";
1826 substate->req = req;
1827 substate->ctdb = ctdb;
1828 substate->header = *header;
1829 substate->reply.rdata.opcode = request->opcode;
1831 subreq = recover_send(substate, state->ev, state->ctdb);
1832 if (subreq == NULL) {
1833 talloc_free(substate);
1836 tevent_req_set_callback(subreq, set_recmode_callback, substate);
1838 ctdb->vnn_map->recmode = CTDB_RECOVERY_ACTIVE;
1842 client_send_control(req, header, &reply);
1846 static void control_db_attach(TALLOC_CTX *mem_ctx,
1847 struct tevent_req *req,
1848 struct ctdb_req_header *header,
1849 struct ctdb_req_control *request)
1851 struct client_state *state = tevent_req_data(
1852 req, struct client_state);
1853 struct ctdbd_context *ctdb = state->ctdb;
1854 struct ctdb_reply_control reply;
1855 struct database *db;
1857 reply.rdata.opcode = request->opcode;
1859 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
1860 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
1865 db = database_new(ctdb->db_map, request->rdata.data.db_name, 0);
1868 reply.errmsg = "Failed to attach database";
1869 client_send_control(req, header, &reply);
1874 reply.rdata.data.db_id = db->id;
1876 reply.errmsg = NULL;
1877 client_send_control(req, header, &reply);
1880 static void srvid_handler(uint64_t srvid, TDB_DATA data, void *private_data)
1882 printf("Received a message for SRVID 0x%"PRIx64"\n", srvid);
1885 static void control_register_srvid(TALLOC_CTX *mem_ctx,
1886 struct tevent_req *req,
1887 struct ctdb_req_header *header,
1888 struct ctdb_req_control *request)
1890 struct client_state *state = tevent_req_data(
1891 req, struct client_state);
1892 struct ctdbd_context *ctdb = state->ctdb;
1893 struct ctdb_reply_control reply;
1896 reply.rdata.opcode = request->opcode;
1898 ret = srvid_register(ctdb->srv, state, request->srvid,
1899 srvid_handler, state);
1902 reply.errmsg = "Memory error";
1906 DEBUG(DEBUG_INFO, ("Register srvid 0x%"PRIx64"\n", request->srvid));
1909 reply.errmsg = NULL;
1912 client_send_control(req, header, &reply);
1915 static void control_deregister_srvid(TALLOC_CTX *mem_ctx,
1916 struct tevent_req *req,
1917 struct ctdb_req_header *header,
1918 struct ctdb_req_control *request)
1920 struct client_state *state = tevent_req_data(
1921 req, struct client_state);
1922 struct ctdbd_context *ctdb = state->ctdb;
1923 struct ctdb_reply_control reply;
1926 reply.rdata.opcode = request->opcode;
1928 ret = srvid_deregister(ctdb->srv, request->srvid, state);
1931 reply.errmsg = "srvid not registered";
1935 DEBUG(DEBUG_INFO, ("Deregister srvid 0x%"PRIx64"\n", request->srvid));
1938 reply.errmsg = NULL;
1941 client_send_control(req, header, &reply);
1944 static void control_get_dbname(TALLOC_CTX *mem_ctx,
1945 struct tevent_req *req,
1946 struct ctdb_req_header *header,
1947 struct ctdb_req_control *request)
1949 struct client_state *state = tevent_req_data(
1950 req, struct client_state);
1951 struct ctdbd_context *ctdb = state->ctdb;
1952 struct ctdb_reply_control reply;
1953 struct database *db;
1955 reply.rdata.opcode = request->opcode;
1957 db = database_find(ctdb->db_map, request->rdata.data.db_id);
1959 reply.status = ENOENT;
1960 reply.errmsg = "Database not found";
1962 reply.rdata.data.db_name = talloc_strdup(mem_ctx, db->name);
1963 if (reply.rdata.data.db_name == NULL) {
1964 reply.status = ENOMEM;
1965 reply.errmsg = "Memory error";
1968 reply.errmsg = NULL;
1972 client_send_control(req, header, &reply);
1975 static void control_get_pid(TALLOC_CTX *mem_ctx,
1976 struct tevent_req *req,
1977 struct ctdb_req_header *header,
1978 struct ctdb_req_control *request)
1980 struct ctdb_reply_control reply;
1982 reply.rdata.opcode = request->opcode;
1983 reply.status = getpid();
1984 reply.errmsg = NULL;
1986 client_send_control(req, header, &reply);
1989 static void control_get_recmaster(TALLOC_CTX *mem_ctx,
1990 struct tevent_req *req,
1991 struct ctdb_req_header *header,
1992 struct ctdb_req_control *request)
1994 struct client_state *state = tevent_req_data(
1995 req, struct client_state);
1996 struct ctdbd_context *ctdb = state->ctdb;
1997 struct ctdb_reply_control reply;
1999 reply.rdata.opcode = request->opcode;
2000 reply.status = ctdb->node_map->recmaster;
2001 reply.errmsg = NULL;
2003 client_send_control(req, header, &reply);
2006 static void control_get_pnn(TALLOC_CTX *mem_ctx,
2007 struct tevent_req *req,
2008 struct ctdb_req_header *header,
2009 struct ctdb_req_control *request)
2011 struct ctdb_reply_control reply;
2013 reply.rdata.opcode = request->opcode;
2014 reply.status = header->destnode;
2015 reply.errmsg = NULL;
2017 client_send_control(req, header, &reply);
2020 static void control_shutdown(TALLOC_CTX *mem_ctx,
2021 struct tevent_req *req,
2022 struct ctdb_req_header *hdr,
2023 struct ctdb_req_control *request)
2025 struct client_state *state = tevent_req_data(
2026 req, struct client_state);
2031 static void control_set_tunable(TALLOC_CTX *mem_ctx,
2032 struct tevent_req *req,
2033 struct ctdb_req_header *header,
2034 struct ctdb_req_control *request)
2036 struct client_state *state = tevent_req_data(
2037 req, struct client_state);
2038 struct ctdbd_context *ctdb = state->ctdb;
2039 struct ctdb_reply_control reply;
2042 reply.rdata.opcode = request->opcode;
2043 reply.errmsg = NULL;
2045 ret = ctdb_tunable_set_value(&ctdb->tun_list,
2046 request->rdata.data.tunable->name,
2047 request->rdata.data.tunable->value,
2051 } else if (obsolete) {
2057 client_send_control(req, header, &reply);
2060 static void control_get_tunable(TALLOC_CTX *mem_ctx,
2061 struct tevent_req *req,
2062 struct ctdb_req_header *header,
2063 struct ctdb_req_control *request)
2065 struct client_state *state = tevent_req_data(
2066 req, struct client_state);
2067 struct ctdbd_context *ctdb = state->ctdb;
2068 struct ctdb_reply_control reply;
2072 reply.rdata.opcode = request->opcode;
2073 reply.errmsg = NULL;
2075 ret = ctdb_tunable_get_value(&ctdb->tun_list,
2076 request->rdata.data.tun_var, &value);
2080 reply.rdata.data.tun_value = value;
2084 client_send_control(req, header, &reply);
2087 static void control_list_tunables(TALLOC_CTX *mem_ctx,
2088 struct tevent_req *req,
2089 struct ctdb_req_header *header,
2090 struct ctdb_req_control *request)
2092 struct ctdb_reply_control reply;
2093 struct ctdb_var_list *var_list;
2095 reply.rdata.opcode = request->opcode;
2096 reply.errmsg = NULL;
2098 var_list = ctdb_tunable_names(mem_ctx);
2099 if (var_list == NULL) {
2102 reply.rdata.data.tun_var_list = var_list;
2106 client_send_control(req, header, &reply);
2109 static void control_modify_flags(TALLOC_CTX *mem_ctx,
2110 struct tevent_req *req,
2111 struct ctdb_req_header *header,
2112 struct ctdb_req_control *request)
2114 struct client_state *state = tevent_req_data(
2115 req, struct client_state);
2116 struct ctdbd_context *ctdb = state->ctdb;
2117 struct ctdb_node_flag_change *change = request->rdata.data.flag_change;
2118 struct ctdb_reply_control reply;
2121 reply.rdata.opcode = request->opcode;
2123 if ((change->old_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) ||
2124 (change->new_flags & ~NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2126 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
2127 reply.status = EINVAL;
2128 reply.errmsg = "Failed to MODIFY_FLAGS";
2129 client_send_control(req, header, &reply);
2133 /* There's all sorts of broadcast weirdness here. Only change
2134 * the specified node, not the destination node of the
2136 node = &ctdb->node_map->node[change->pnn];
2139 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0 &&
2140 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0) {
2141 DEBUG(DEBUG_INFO,("Disabling node %d\n", header->destnode));
2142 node->flags |= NODE_FLAGS_PERMANENTLY_DISABLED;
2147 change->old_flags & NODE_FLAGS_PERMANENTLY_DISABLED) != 0 &&
2148 (change->new_flags & NODE_FLAGS_PERMANENTLY_DISABLED) == 0) {
2149 DEBUG(DEBUG_INFO,("Enabling node %d\n", header->destnode));
2150 node->flags &= ~NODE_FLAGS_PERMANENTLY_DISABLED;
2154 DEBUG(DEBUG_INFO, ("Flags unchanged for node %d\n", header->destnode));
2158 reply.errmsg = NULL;
2159 client_send_control(req, header, &reply);
2162 static void control_get_all_tunables(TALLOC_CTX *mem_ctx,
2163 struct tevent_req *req,
2164 struct ctdb_req_header *header,
2165 struct ctdb_req_control *request)
2167 struct client_state *state = tevent_req_data(
2168 req, struct client_state);
2169 struct ctdbd_context *ctdb = state->ctdb;
2170 struct ctdb_reply_control reply;
2172 reply.rdata.opcode = request->opcode;
2173 reply.rdata.data.tun_list = &ctdb->tun_list;
2175 reply.errmsg = NULL;
2177 client_send_control(req, header, &reply);
2180 static void control_db_attach_persistent(TALLOC_CTX *mem_ctx,
2181 struct tevent_req *req,
2182 struct ctdb_req_header *header,
2183 struct ctdb_req_control *request)
2185 struct client_state *state = tevent_req_data(
2186 req, struct client_state);
2187 struct ctdbd_context *ctdb = state->ctdb;
2188 struct ctdb_reply_control reply;
2189 struct database *db;
2191 reply.rdata.opcode = request->opcode;
2193 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
2194 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
2199 db = database_new(ctdb->db_map, request->rdata.data.db_name,
2200 CTDB_DB_FLAGS_PERSISTENT);
2203 reply.errmsg = "Failed to attach database";
2204 client_send_control(req, header, &reply);
2209 reply.rdata.data.db_id = db->id;
2211 reply.errmsg = NULL;
2212 client_send_control(req, header, &reply);
2215 static void control_uptime(TALLOC_CTX *mem_ctx,
2216 struct tevent_req *req,
2217 struct ctdb_req_header *header,
2218 struct ctdb_req_control *request)
2220 struct client_state *state = tevent_req_data(
2221 req, struct client_state);
2222 struct ctdbd_context *ctdb = state->ctdb;
2223 struct ctdb_reply_control reply;
2224 struct ctdb_uptime *uptime;;
2226 reply.rdata.opcode = request->opcode;
2228 uptime = talloc_zero(mem_ctx, struct ctdb_uptime);
2229 if (uptime == NULL) {
2233 uptime->current_time = tevent_timeval_current();
2234 uptime->ctdbd_start_time = ctdb->start_time;
2235 uptime->last_recovery_started = ctdb->recovery_start_time;
2236 uptime->last_recovery_finished = ctdb->recovery_end_time;
2238 reply.rdata.data.uptime = uptime;
2240 reply.errmsg = NULL;
2241 client_send_control(req, header, &reply);
2246 reply.errmsg = "Memory error";
2247 client_send_control(req, header, &reply);
2250 static void control_reload_nodes_file(TALLOC_CTX *mem_ctx,
2251 struct tevent_req *req,
2252 struct ctdb_req_header *header,
2253 struct ctdb_req_control *request)
2255 struct client_state *state = tevent_req_data(
2256 req, struct client_state);
2257 struct ctdbd_context *ctdb = state->ctdb;
2258 struct ctdb_reply_control reply;
2259 struct ctdb_node_map *nodemap;
2260 struct node_map *node_map = ctdb->node_map;
2263 reply.rdata.opcode = request->opcode;
2265 nodemap = read_nodes_file(mem_ctx, header->destnode);
2266 if (nodemap == NULL) {
2270 for (i=0; i<nodemap->num; i++) {
2273 if (i < node_map->num_nodes &&
2274 ctdb_sock_addr_same(&nodemap->node[i].addr,
2275 &node_map->node[i].addr)) {
2279 if (nodemap->node[i].flags & NODE_FLAGS_DELETED) {
2282 node = &node_map->node[i];
2284 node->flags |= NODE_FLAGS_DELETED;
2285 ret = ctdb_sock_addr_from_string("0.0.0.0", &node->addr,
2288 /* Can't happen, but Coverity... */
2295 if (i < node_map->num_nodes &&
2296 node_map->node[i].flags & NODE_FLAGS_DELETED) {
2297 node = &node_map->node[i];
2299 node->flags &= ~NODE_FLAGS_DELETED;
2300 node->addr = nodemap->node[i].addr;
2305 node_map->node = talloc_realloc(node_map, node_map->node,
2307 node_map->num_nodes+1);
2308 if (node_map->node == NULL) {
2311 node = &node_map->node[node_map->num_nodes];
2313 node->addr = nodemap->node[i].addr;
2314 node->pnn = nodemap->node[i].pnn;
2316 node->capabilities = CTDB_CAP_DEFAULT;
2317 node->recovery_disabled = false;
2318 node->recovery_substate = NULL;
2320 node_map->num_nodes += 1;
2323 talloc_free(nodemap);
2326 reply.errmsg = NULL;
2327 client_send_control(req, header, &reply);
2332 reply.errmsg = "Memory error";
2333 client_send_control(req, header, &reply);
2336 static void control_get_capabilities(TALLOC_CTX *mem_ctx,
2337 struct tevent_req *req,
2338 struct ctdb_req_header *header,
2339 struct ctdb_req_control *request)
2341 struct client_state *state = tevent_req_data(
2342 req, struct client_state);
2343 struct ctdbd_context *ctdb = state->ctdb;
2344 struct ctdb_reply_control reply;
2348 reply.rdata.opcode = request->opcode;
2350 node = &ctdb->node_map->node[header->destnode];
2351 caps = node->capabilities;
2353 if (node->flags & NODE_FLAGS_FAKE_TIMEOUT) {
2354 /* Don't send reply */
2358 reply.rdata.data.caps = caps;
2360 reply.errmsg = NULL;
2362 client_send_control(req, header, &reply);
2365 static void control_release_ip(TALLOC_CTX *mem_ctx,
2366 struct tevent_req *req,
2367 struct ctdb_req_header *header,
2368 struct ctdb_req_control *request)
2370 struct client_state *state = tevent_req_data(
2371 req, struct client_state);
2372 struct ctdbd_context *ctdb = state->ctdb;
2373 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2374 struct ctdb_reply_control reply;
2375 struct ctdb_public_ip_list *ips = NULL;
2376 struct ctdb_public_ip *t = NULL;
2379 reply.rdata.opcode = request->opcode;
2381 if (ctdb->known_ips == NULL) {
2382 D_INFO("RELEASE_IP %s - not a public IP\n",
2383 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2387 ips = &ctdb->known_ips[header->destnode];
2390 for (i = 0; i < ips->num; i++) {
2391 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2397 D_INFO("RELEASE_IP %s - not a public IP\n",
2398 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2402 if (t->pnn != header->destnode) {
2403 if (header->destnode == ip->pnn) {
2404 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2405 ctdb_sock_addr_to_string(mem_ctx,
2409 reply.errmsg = "RELEASE_IP to TAKE_IP node";
2410 client_send_control(req, header, &reply);
2414 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2415 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2419 D_NOTICE("RELEASE_IP %s - to node %d\n",
2420 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false),
2427 reply.errmsg = NULL;
2428 client_send_control(req, header, &reply);
2431 static void control_takeover_ip(TALLOC_CTX *mem_ctx,
2432 struct tevent_req *req,
2433 struct ctdb_req_header *header,
2434 struct ctdb_req_control *request)
2436 struct client_state *state = tevent_req_data(
2437 req, struct client_state);
2438 struct ctdbd_context *ctdb = state->ctdb;
2439 struct ctdb_public_ip *ip = request->rdata.data.pubip;
2440 struct ctdb_reply_control reply;
2441 struct ctdb_public_ip_list *ips = NULL;
2442 struct ctdb_public_ip *t = NULL;
2445 reply.rdata.opcode = request->opcode;
2447 if (ctdb->known_ips == NULL) {
2448 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2449 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2453 ips = &ctdb->known_ips[header->destnode];
2456 for (i = 0; i < ips->num; i++) {
2457 if (ctdb_sock_addr_same_ip(&ips->ip[i].addr, &ip->addr)) {
2463 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2464 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2468 if (t->pnn == header->destnode) {
2469 D_INFO("TAKEOVER_IP %s - redundant\n",
2470 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2472 D_NOTICE("TAKEOVER_IP %s\n",
2473 ctdb_sock_addr_to_string(mem_ctx, &ip->addr, false));
2479 reply.errmsg = NULL;
2480 client_send_control(req, header, &reply);
2483 static void control_get_public_ips(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_reply_control reply;
2492 struct ctdb_public_ip_list *ips = NULL;
2494 reply.rdata.opcode = request->opcode;
2496 if (ctdb->known_ips == NULL) {
2497 /* No IPs defined so create a dummy empty struct and ship it */
2498 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2500 reply.status = ENOMEM;
2501 reply.errmsg = "Memory error";
2507 ips = &ctdb->known_ips[header->destnode];
2509 if (request->flags & CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE) {
2510 /* If runstate is not RUNNING or a node is then return
2511 * no available IPs. Don't worry about interface
2512 * states here - we're not faking down to that level.
2514 if (ctdb->runstate != CTDB_RUNSTATE_RUNNING) {
2515 /* No available IPs: return dummy empty struct */
2516 ips = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2518 reply.status = ENOMEM;
2519 reply.errmsg = "Memory error";
2526 reply.rdata.data.pubip_list = ips;
2528 reply.errmsg = NULL;
2531 client_send_control(req, header, &reply);
2534 static void control_get_nodemap(TALLOC_CTX *mem_ctx,
2535 struct tevent_req *req,
2536 struct ctdb_req_header *header,
2537 struct ctdb_req_control *request)
2539 struct client_state *state = tevent_req_data(
2540 req, struct client_state);
2541 struct ctdbd_context *ctdb = state->ctdb;
2542 struct ctdb_reply_control reply;
2543 struct ctdb_node_map *nodemap;
2547 reply.rdata.opcode = request->opcode;
2549 nodemap = talloc_zero(mem_ctx, struct ctdb_node_map);
2550 if (nodemap == NULL) {
2554 nodemap->num = ctdb->node_map->num_nodes;
2555 nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
2557 if (nodemap->node == NULL) {
2561 for (i=0; i<nodemap->num; i++) {
2562 node = &ctdb->node_map->node[i];
2563 nodemap->node[i] = (struct ctdb_node_and_flags) {
2565 .flags = node->flags,
2570 reply.rdata.data.nodemap = nodemap;
2572 reply.errmsg = NULL;
2573 client_send_control(req, header, &reply);
2578 reply.errmsg = "Memory error";
2579 client_send_control(req, header, &reply);
2582 static void control_get_reclock_file(TALLOC_CTX *mem_ctx,
2583 struct tevent_req *req,
2584 struct ctdb_req_header *header,
2585 struct ctdb_req_control *request)
2587 struct client_state *state = tevent_req_data(
2588 req, struct client_state);
2589 struct ctdbd_context *ctdb = state->ctdb;
2590 struct ctdb_reply_control reply;
2592 reply.rdata.opcode = request->opcode;
2594 if (ctdb->reclock != NULL) {
2595 reply.rdata.data.reclock_file =
2596 talloc_strdup(mem_ctx, ctdb->reclock);
2597 if (reply.rdata.data.reclock_file == NULL) {
2598 reply.status = ENOMEM;
2599 reply.errmsg = "Memory error";
2603 reply.rdata.data.reclock_file = NULL;
2607 reply.errmsg = NULL;
2610 client_send_control(req, header, &reply);
2613 static void control_stop_node(TALLOC_CTX *mem_ctx,
2614 struct tevent_req *req,
2615 struct ctdb_req_header *header,
2616 struct ctdb_req_control *request)
2618 struct client_state *state = tevent_req_data(
2619 req, struct client_state);
2620 struct ctdbd_context *ctdb = state->ctdb;
2621 struct ctdb_reply_control reply;
2623 reply.rdata.opcode = request->opcode;
2625 DEBUG(DEBUG_INFO, ("Stopping node\n"));
2626 ctdb->node_map->node[header->destnode].flags |= NODE_FLAGS_STOPPED;
2629 reply.errmsg = NULL;
2631 client_send_control(req, header, &reply);
2635 static void control_continue_node(TALLOC_CTX *mem_ctx,
2636 struct tevent_req *req,
2637 struct ctdb_req_header *header,
2638 struct ctdb_req_control *request)
2640 struct client_state *state = tevent_req_data(
2641 req, struct client_state);
2642 struct ctdbd_context *ctdb = state->ctdb;
2643 struct ctdb_reply_control reply;
2645 reply.rdata.opcode = request->opcode;
2647 DEBUG(DEBUG_INFO, ("Continue node\n"));
2648 ctdb->node_map->node[header->destnode].flags &= ~NODE_FLAGS_STOPPED;
2651 reply.errmsg = NULL;
2653 client_send_control(req, header, &reply);
2657 static void set_ban_state_callback(struct tevent_req *subreq)
2659 struct node *node = tevent_req_callback_data(
2660 subreq, struct node);
2663 status = tevent_wakeup_recv(subreq);
2664 TALLOC_FREE(subreq);
2666 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
2669 node->flags &= ~NODE_FLAGS_BANNED;
2672 static void control_set_ban_state(TALLOC_CTX *mem_ctx,
2673 struct tevent_req *req,
2674 struct ctdb_req_header *header,
2675 struct ctdb_req_control *request)
2677 struct client_state *state = tevent_req_data(
2678 req, struct client_state);
2679 struct tevent_req *subreq;
2680 struct ctdbd_context *ctdb = state->ctdb;
2681 struct ctdb_ban_state *ban = request->rdata.data.ban_state;
2682 struct ctdb_reply_control reply;
2685 reply.rdata.opcode = request->opcode;
2687 if (ban->pnn != header->destnode) {
2689 ("SET_BAN_STATE control for PNN %d rejected\n",
2691 reply.status = EINVAL;
2695 node = &ctdb->node_map->node[header->destnode];
2697 if (ban->time == 0) {
2698 DEBUG(DEBUG_INFO,("Unbanning this node\n"));
2699 node->flags &= ~NODE_FLAGS_BANNED;
2703 subreq = tevent_wakeup_send(ctdb->node_map, state->ev,
2704 tevent_timeval_current_ofs(
2706 if (subreq == NULL) {
2707 reply.status = ENOMEM;
2710 tevent_req_set_callback(subreq, set_ban_state_callback, node);
2712 DEBUG(DEBUG_INFO, ("Banning this node for %d seconds\n", ban->time));
2713 node->flags |= NODE_FLAGS_BANNED;
2714 ctdb->vnn_map->generation = INVALID_GENERATION;
2718 reply.errmsg = NULL;
2720 client_send_control(req, header, &reply);
2724 reply.errmsg = "Failed to ban node";
2727 static void control_get_db_seqnum(TALLOC_CTX *mem_ctx,
2728 struct tevent_req *req,
2729 struct ctdb_req_header *header,
2730 struct ctdb_req_control *request)
2732 struct client_state *state = tevent_req_data(
2733 req, struct client_state);
2734 struct ctdbd_context *ctdb = state->ctdb;
2735 struct ctdb_reply_control reply;
2736 struct database *db;
2739 reply.rdata.opcode = request->opcode;
2741 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2743 reply.status = ENOENT;
2744 reply.errmsg = "Database not found";
2748 ret = database_seqnum(db, &seqnum);
2750 reply.rdata.data.seqnum = seqnum;
2752 reply.errmsg = NULL;
2755 reply.errmsg = "Failed to get seqnum";
2759 client_send_control(req, header, &reply);
2762 static void control_db_get_health(TALLOC_CTX *mem_ctx,
2763 struct tevent_req *req,
2764 struct ctdb_req_header *header,
2765 struct ctdb_req_control *request)
2767 struct client_state *state = tevent_req_data(
2768 req, struct client_state);
2769 struct ctdbd_context *ctdb = state->ctdb;
2770 struct ctdb_reply_control reply;
2771 struct database *db;
2773 reply.rdata.opcode = request->opcode;
2775 db = database_find(ctdb->db_map, request->rdata.data.db_id);
2777 reply.status = ENOENT;
2778 reply.errmsg = "Database not found";
2780 reply.rdata.data.reason = NULL;
2782 reply.errmsg = NULL;
2785 client_send_control(req, header, &reply);
2788 static struct ctdb_iface_list *get_ctdb_iface_list(TALLOC_CTX *mem_ctx,
2789 struct ctdbd_context *ctdb)
2791 struct ctdb_iface_list *iface_list;
2792 struct interface *iface;
2795 iface_list = talloc_zero(mem_ctx, struct ctdb_iface_list);
2796 if (iface_list == NULL) {
2800 iface_list->num = ctdb->iface_map->num;
2801 iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
2803 if (iface_list->iface == NULL) {
2804 TALLOC_FREE(iface_list);
2808 for (i=0; i<iface_list->num; i++) {
2809 iface = &ctdb->iface_map->iface[i];
2810 iface_list->iface[i] = (struct ctdb_iface) {
2811 .link_state = iface->link_up,
2812 .references = iface->references,
2814 strlcpy(iface_list->iface[i].name, iface->name,
2815 sizeof(iface_list->iface[i].name));
2822 static void control_get_public_ip_info(TALLOC_CTX *mem_ctx,
2823 struct tevent_req *req,
2824 struct ctdb_req_header *header,
2825 struct ctdb_req_control *request)
2827 struct client_state *state = tevent_req_data(
2828 req, struct client_state);
2829 struct ctdbd_context *ctdb = state->ctdb;
2830 struct ctdb_reply_control reply;
2831 ctdb_sock_addr *addr = request->rdata.data.addr;
2832 struct ctdb_public_ip_list *known = NULL;
2833 struct ctdb_public_ip_info *info = NULL;
2836 reply.rdata.opcode = request->opcode;
2838 info = talloc_zero(mem_ctx, struct ctdb_public_ip_info);
2840 reply.status = ENOMEM;
2841 reply.errmsg = "Memory error";
2845 reply.rdata.data.ipinfo = info;
2847 if (ctdb->known_ips != NULL) {
2848 known = &ctdb->known_ips[header->destnode];
2850 /* No IPs defined so create a dummy empty struct and
2851 * fall through. The given IP won't be matched
2854 known = talloc_zero(mem_ctx, struct ctdb_public_ip_list);;
2855 if (known == NULL) {
2856 reply.status = ENOMEM;
2857 reply.errmsg = "Memory error";
2862 for (i = 0; i < known->num; i++) {
2863 if (ctdb_sock_addr_same_ip(&known->ip[i].addr,
2869 if (i == known->num) {
2870 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
2871 ctdb_sock_addr_to_string(mem_ctx, addr, false));
2873 reply.errmsg = "Unknown address";
2877 info->ip = known->ip[i];
2879 /* The fake PUBLICIPS stanza and resulting known_ips data
2880 * don't know anything about interfaces, so completely fake
2883 info->active_idx = 0;
2885 info->ifaces = get_ctdb_iface_list(mem_ctx, ctdb);
2886 if (info->ifaces == NULL) {
2887 reply.status = ENOMEM;
2888 reply.errmsg = "Memory error";
2893 reply.errmsg = NULL;
2896 client_send_control(req, header, &reply);
2899 static void control_get_ifaces(TALLOC_CTX *mem_ctx,
2900 struct tevent_req *req,
2901 struct ctdb_req_header *header,
2902 struct ctdb_req_control *request)
2904 struct client_state *state = tevent_req_data(
2905 req, struct client_state);
2906 struct ctdbd_context *ctdb = state->ctdb;
2907 struct ctdb_reply_control reply;
2908 struct ctdb_iface_list *iface_list;
2910 reply.rdata.opcode = request->opcode;
2912 iface_list = get_ctdb_iface_list(mem_ctx, ctdb);
2913 if (iface_list == NULL) {
2917 reply.rdata.data.iface_list = iface_list;
2919 reply.errmsg = NULL;
2920 client_send_control(req, header, &reply);
2925 reply.errmsg = "Memory error";
2926 client_send_control(req, header, &reply);
2929 static void control_set_iface_link_state(TALLOC_CTX *mem_ctx,
2930 struct tevent_req *req,
2931 struct ctdb_req_header *header,
2932 struct ctdb_req_control *request)
2934 struct client_state *state = tevent_req_data(
2935 req, struct client_state);
2936 struct ctdbd_context *ctdb = state->ctdb;
2937 struct ctdb_reply_control reply;
2938 struct ctdb_iface *in_iface;
2939 struct interface *iface = NULL;
2940 bool link_up = false;
2943 reply.rdata.opcode = request->opcode;
2945 in_iface = request->rdata.data.iface;
2947 if (in_iface->name[CTDB_IFACE_SIZE] != '\0') {
2948 reply.errmsg = "interface name not terminated";
2952 switch (in_iface->link_state) {
2962 reply.errmsg = "invalid link state";
2966 if (in_iface->references != 0) {
2967 reply.errmsg = "references should be 0";
2971 for (i=0; i<ctdb->iface_map->num; i++) {
2972 if (strcmp(ctdb->iface_map->iface[i].name,
2973 in_iface->name) == 0) {
2974 iface = &ctdb->iface_map->iface[i];
2979 if (iface == NULL) {
2980 reply.errmsg = "interface not found";
2984 iface->link_up = link_up;
2987 reply.errmsg = NULL;
2988 client_send_control(req, header, &reply);
2993 client_send_control(req, header, &reply);
2996 static void control_set_db_readonly(TALLOC_CTX *mem_ctx,
2997 struct tevent_req *req,
2998 struct ctdb_req_header *header,
2999 struct ctdb_req_control *request)
3001 struct client_state *state = tevent_req_data(
3002 req, struct client_state);
3003 struct ctdbd_context *ctdb = state->ctdb;
3004 struct ctdb_reply_control reply;
3005 struct database *db;
3007 reply.rdata.opcode = request->opcode;
3009 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3011 reply.status = ENOENT;
3012 reply.errmsg = "Database not found";
3016 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3017 reply.status = EINVAL;
3018 reply.errmsg = "Can not set READONLY on persistent db";
3022 db->flags |= CTDB_DB_FLAGS_READONLY;
3024 reply.errmsg = NULL;
3027 client_send_control(req, header, &reply);
3030 static void control_set_db_sticky(TALLOC_CTX *mem_ctx,
3031 struct tevent_req *req,
3032 struct ctdb_req_header *header,
3033 struct ctdb_req_control *request)
3035 struct client_state *state = tevent_req_data(
3036 req, struct client_state);
3037 struct ctdbd_context *ctdb = state->ctdb;
3038 struct ctdb_reply_control reply;
3039 struct database *db;
3041 reply.rdata.opcode = request->opcode;
3043 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3045 reply.status = ENOENT;
3046 reply.errmsg = "Database not found";
3050 if (db->flags & CTDB_DB_FLAGS_PERSISTENT) {
3051 reply.status = EINVAL;
3052 reply.errmsg = "Can not set STICKY on persistent db";
3056 db->flags |= CTDB_DB_FLAGS_STICKY;
3058 reply.errmsg = NULL;
3061 client_send_control(req, header, &reply);
3064 static void control_ipreallocated(TALLOC_CTX *mem_ctx,
3065 struct tevent_req *req,
3066 struct ctdb_req_header *header,
3067 struct ctdb_req_control *request)
3069 struct ctdb_reply_control reply;
3071 /* Always succeed */
3072 reply.rdata.opcode = request->opcode;
3074 reply.errmsg = NULL;
3076 client_send_control(req, header, &reply);
3079 static void control_get_runstate(TALLOC_CTX *mem_ctx,
3080 struct tevent_req *req,
3081 struct ctdb_req_header *header,
3082 struct ctdb_req_control *request)
3084 struct client_state *state = tevent_req_data(
3085 req, struct client_state);
3086 struct ctdbd_context *ctdb = state->ctdb;
3087 struct ctdb_reply_control reply;
3089 reply.rdata.opcode = request->opcode;
3090 reply.rdata.data.runstate = ctdb->runstate;
3092 reply.errmsg = NULL;
3094 client_send_control(req, header, &reply);
3097 static void control_get_nodes_file(TALLOC_CTX *mem_ctx,
3098 struct tevent_req *req,
3099 struct ctdb_req_header *header,
3100 struct ctdb_req_control *request)
3102 struct ctdb_reply_control reply;
3103 struct ctdb_node_map *nodemap;
3105 reply.rdata.opcode = request->opcode;
3107 nodemap = read_nodes_file(mem_ctx, header->destnode);
3108 if (nodemap == NULL) {
3112 reply.rdata.data.nodemap = nodemap;
3114 reply.errmsg = NULL;
3115 client_send_control(req, header, &reply);
3120 reply.errmsg = "Failed to read nodes file";
3121 client_send_control(req, header, &reply);
3124 static void control_db_open_flags(TALLOC_CTX *mem_ctx,
3125 struct tevent_req *req,
3126 struct ctdb_req_header *header,
3127 struct ctdb_req_control *request)
3129 struct client_state *state = tevent_req_data(
3130 req, struct client_state);
3131 struct ctdbd_context *ctdb = state->ctdb;
3132 struct ctdb_reply_control reply;
3133 struct database *db;
3135 reply.rdata.opcode = request->opcode;
3137 db = database_find(ctdb->db_map, request->rdata.data.db_id);
3139 reply.status = ENOENT;
3140 reply.errmsg = "Database not found";
3142 reply.rdata.data.tdb_flags = database_flags(db->flags);
3144 reply.errmsg = NULL;
3147 client_send_control(req, header, &reply);
3150 static void control_db_attach_replicated(TALLOC_CTX *mem_ctx,
3151 struct tevent_req *req,
3152 struct ctdb_req_header *header,
3153 struct ctdb_req_control *request)
3155 struct client_state *state = tevent_req_data(
3156 req, struct client_state);
3157 struct ctdbd_context *ctdb = state->ctdb;
3158 struct ctdb_reply_control reply;
3159 struct database *db;
3161 reply.rdata.opcode = request->opcode;
3163 for (db = ctdb->db_map->db; db != NULL; db = db->next) {
3164 if (strcmp(db->name, request->rdata.data.db_name) == 0) {
3169 db = database_new(ctdb->db_map, request->rdata.data.db_name,
3170 CTDB_DB_FLAGS_REPLICATED);
3173 reply.errmsg = "Failed to attach database";
3174 client_send_control(req, header, &reply);
3179 reply.rdata.data.db_id = db->id;
3181 reply.errmsg = NULL;
3182 client_send_control(req, header, &reply);
3185 static void control_check_pid_srvid(TALLOC_CTX *mem_ctx,
3186 struct tevent_req *req,
3187 struct ctdb_req_header *header,
3188 struct ctdb_req_control *request)
3190 struct client_state *state = tevent_req_data(
3191 req, struct client_state);
3192 struct ctdbd_context *ctdb = state->ctdb;
3193 struct ctdb_client *client;
3194 struct client_state *cstate;
3195 struct ctdb_reply_control reply;
3196 bool pid_found, srvid_found;
3199 reply.rdata.opcode = request->opcode;
3202 srvid_found = false;
3204 for (client=ctdb->client_list; client != NULL; client=client->next) {
3205 if (client->pid == request->rdata.data.pid_srvid->pid) {
3207 cstate = (struct client_state *)client->state;
3208 ret = srvid_exists(ctdb->srv,
3209 request->rdata.data.pid_srvid->srvid,
3213 ret = kill(cstate->pid, 0);
3216 reply.errmsg = strerror(errno);
3219 reply.errmsg = NULL;
3227 reply.errmsg = "No client for PID";
3228 } else if (! srvid_found) {
3230 reply.errmsg = "No client for PID and SRVID";
3233 client_send_control(req, header, &reply);
3236 static bool fake_control_failure(TALLOC_CTX *mem_ctx,
3237 struct tevent_req *req,
3238 struct ctdb_req_header *header,
3239 struct ctdb_req_control *request)
3241 struct client_state *state = tevent_req_data(
3242 req, struct client_state);
3243 struct ctdbd_context *ctdb = state->ctdb;
3244 struct ctdb_reply_control reply;
3245 struct fake_control_failure *f = NULL;
3247 D_DEBUG("Checking fake control failure for control %u on node %u\n",
3248 request->opcode, header->destnode);
3249 for (f = ctdb->control_failures; f != NULL; f = f->next) {
3250 if (f->opcode == request->opcode &&
3251 (f->pnn == header->destnode ||
3252 f->pnn == CTDB_UNKNOWN_PNN)) {
3254 reply.rdata.opcode = request->opcode;
3255 if (strcmp(f->error, "TIMEOUT") == 0) {
3256 /* Causes no reply */
3257 D_ERR("Control %u fake timeout on node %u\n",
3258 request->opcode, header->destnode);
3260 } else if (strcmp(f->error, "ERROR") == 0) {
3261 D_ERR("Control %u fake error on node %u\n",
3262 request->opcode, header->destnode);
3264 reply.errmsg = f->comment;
3265 client_send_control(req, header, &reply);
3274 static void control_error(TALLOC_CTX *mem_ctx,
3275 struct tevent_req *req,
3276 struct ctdb_req_header *header,
3277 struct ctdb_req_control *request)
3279 struct ctdb_reply_control reply;
3281 reply.rdata.opcode = request->opcode;
3283 reply.errmsg = "Not implemented";
3285 client_send_control(req, header, &reply);
3289 * Handling protocol - messages
3292 struct disable_recoveries_state {
3296 static void disable_recoveries_callback(struct tevent_req *subreq)
3298 struct disable_recoveries_state *substate = tevent_req_callback_data(
3299 subreq, struct disable_recoveries_state);
3302 status = tevent_wakeup_recv(subreq);
3303 TALLOC_FREE(subreq);
3305 DEBUG(DEBUG_INFO, ("tevent_wakeup_recv failed\n"));
3308 substate->node->recovery_disabled = false;
3309 TALLOC_FREE(substate->node->recovery_substate);
3312 static void message_disable_recoveries(TALLOC_CTX *mem_ctx,
3313 struct tevent_req *req,
3314 struct ctdb_req_header *header,
3315 struct ctdb_req_message *request)
3317 struct client_state *state = tevent_req_data(
3318 req, struct client_state);
3319 struct tevent_req *subreq;
3320 struct ctdbd_context *ctdb = state->ctdb;
3321 struct disable_recoveries_state *substate;
3322 struct ctdb_disable_message *disable = request->data.disable;
3323 struct ctdb_req_message_data reply;
3328 node = &ctdb->node_map->node[header->destnode];
3330 if (disable->timeout == 0) {
3331 TALLOC_FREE(node->recovery_substate);
3332 node->recovery_disabled = false;
3333 DEBUG(DEBUG_INFO, ("Enabled recoveries on node %u\n",
3338 substate = talloc_zero(ctdb->node_map,
3339 struct disable_recoveries_state);
3340 if (substate == NULL) {
3344 substate->node = node;
3346 subreq = tevent_wakeup_send(substate, state->ev,
3347 tevent_timeval_current_ofs(
3348 disable->timeout, 0));
3349 if (subreq == NULL) {
3350 talloc_free(substate);
3353 tevent_req_set_callback(subreq, disable_recoveries_callback, substate);
3355 DEBUG(DEBUG_INFO, ("Disabled recoveries for %d seconds on node %u\n",
3356 disable->timeout, header->destnode));
3357 node->recovery_substate = substate;
3358 node->recovery_disabled = true;
3361 ret = header->destnode;
3364 reply.srvid = disable->srvid;
3365 data.dptr = (uint8_t *)&ret;
3366 data.dsize = sizeof(int);
3369 client_send_message(req, header, &reply);
3372 static void message_takeover_run(TALLOC_CTX *mem_ctx,
3373 struct tevent_req *req,
3374 struct ctdb_req_header *header,
3375 struct ctdb_req_message *request)
3377 struct client_state *state = tevent_req_data(
3378 req, struct client_state);
3379 struct ctdbd_context *ctdb = state->ctdb;
3380 struct ctdb_srvid_message *srvid = request->data.msg;
3381 struct ctdb_req_message_data reply;
3385 if (header->destnode != ctdb->node_map->recmaster) {
3386 /* No reply! Only recmaster replies... */
3390 DEBUG(DEBUG_INFO, ("IP takover run on node %u\n",
3392 ret = header->destnode;
3394 reply.srvid = srvid->srvid;
3395 data.dptr = (uint8_t *)&ret;
3396 data.dsize = sizeof(int);
3399 client_send_message(req, header, &reply);
3403 * Handle a single client
3406 static void client_read_handler(uint8_t *buf, size_t buflen,
3407 void *private_data);
3408 static void client_dead_handler(void *private_data);
3409 static void client_process_packet(struct tevent_req *req,
3410 uint8_t *buf, size_t buflen);
3411 static void client_process_message(struct tevent_req *req,
3412 uint8_t *buf, size_t buflen);
3413 static void client_process_control(struct tevent_req *req,
3414 uint8_t *buf, size_t buflen);
3415 static void client_reply_done(struct tevent_req *subreq);
3417 static struct tevent_req *client_send(TALLOC_CTX *mem_ctx,
3418 struct tevent_context *ev,
3419 int fd, struct ctdbd_context *ctdb,
3422 struct tevent_req *req;
3423 struct client_state *state;
3425 socklen_t crl = sizeof(struct ucred);
3428 req = tevent_req_create(mem_ctx, &state, struct client_state);
3438 ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crl);
3440 tevent_req_error(req, ret);
3441 return tevent_req_post(req, ev);
3443 state->pid = cr.pid;
3445 ret = comm_setup(state, ev, fd, client_read_handler, req,
3446 client_dead_handler, req, &state->comm);
3448 tevent_req_error(req, ret);
3449 return tevent_req_post(req, ev);
3452 ret = client_add(ctdb, state->pid, state);
3454 tevent_req_error(req, ret);
3455 return tevent_req_post(req, ev);
3458 DEBUG(DEBUG_INFO, ("New client fd=%d\n", fd));
3463 static void client_read_handler(uint8_t *buf, size_t buflen,
3466 struct tevent_req *req = talloc_get_type_abort(
3467 private_data, struct tevent_req);
3468 struct client_state *state = tevent_req_data(
3469 req, struct client_state);
3470 struct ctdbd_context *ctdb = state->ctdb;
3471 struct ctdb_req_header header;
3475 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3480 if (buflen != header.length) {
3484 ret = ctdb_req_header_verify(&header, 0);
3489 header_fix_pnn(&header, ctdb);
3491 if (header.destnode == CTDB_BROADCAST_ALL) {
3492 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3493 header.destnode = i;
3495 ctdb_req_header_push(&header, buf, &np);
3496 client_process_packet(req, buf, buflen);
3501 if (header.destnode == CTDB_BROADCAST_CONNECTED) {
3502 for (i=0; i<ctdb->node_map->num_nodes; i++) {
3503 if (ctdb->node_map->node[i].flags &
3504 NODE_FLAGS_DISCONNECTED) {
3508 header.destnode = i;
3510 ctdb_req_header_push(&header, buf, &np);
3511 client_process_packet(req, buf, buflen);
3516 if (header.destnode > ctdb->node_map->num_nodes) {
3517 fprintf(stderr, "Invalid destination pnn 0x%x\n",
3523 if (ctdb->node_map->node[header.destnode].flags & NODE_FLAGS_DISCONNECTED) {
3524 fprintf(stderr, "Packet for disconnected node pnn %u\n",
3529 ctdb_req_header_push(&header, buf, &np);
3530 client_process_packet(req, buf, buflen);
3533 static void client_dead_handler(void *private_data)
3535 struct tevent_req *req = talloc_get_type_abort(
3536 private_data, struct tevent_req);
3538 tevent_req_done(req);
3541 static void client_process_packet(struct tevent_req *req,
3542 uint8_t *buf, size_t buflen)
3544 struct ctdb_req_header header;
3548 ret = ctdb_req_header_pull(buf, buflen, &header, &np);
3553 switch (header.operation) {
3554 case CTDB_REQ_MESSAGE:
3555 client_process_message(req, buf, buflen);
3558 case CTDB_REQ_CONTROL:
3559 client_process_control(req, buf, buflen);
3567 static void client_process_message(struct tevent_req *req,
3568 uint8_t *buf, size_t buflen)
3570 struct client_state *state = tevent_req_data(
3571 req, struct client_state);
3572 struct ctdbd_context *ctdb = state->ctdb;
3573 TALLOC_CTX *mem_ctx;
3574 struct ctdb_req_header header;
3575 struct ctdb_req_message request;
3579 mem_ctx = talloc_new(state);
3580 if (tevent_req_nomem(mem_ctx, req)) {
3584 ret = ctdb_req_message_pull(buf, buflen, &header, mem_ctx, &request);
3586 talloc_free(mem_ctx);
3587 tevent_req_error(req, ret);
3591 header_fix_pnn(&header, ctdb);
3593 if (header.destnode >= ctdb->node_map->num_nodes) {
3594 /* Many messages are not replied to, so just behave as
3595 * though this message was not received */
3596 fprintf(stderr, "Invalid node %d\n", header.destnode);
3597 talloc_free(mem_ctx);
3601 srvid = request.srvid;
3602 DEBUG(DEBUG_INFO, ("request srvid = 0x%"PRIx64"\n", srvid));
3604 if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
3605 message_disable_recoveries(mem_ctx, req, &header, &request);
3606 } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
3607 message_takeover_run(mem_ctx, req, &header, &request);
3611 talloc_free(mem_ctx);
3614 static void client_process_control(struct tevent_req *req,
3615 uint8_t *buf, size_t buflen)
3617 struct client_state *state = tevent_req_data(
3618 req, struct client_state);
3619 struct ctdbd_context *ctdb = state->ctdb;
3620 TALLOC_CTX *mem_ctx;
3621 struct ctdb_req_header header;
3622 struct ctdb_req_control request;
3625 mem_ctx = talloc_new(state);
3626 if (tevent_req_nomem(mem_ctx, req)) {
3630 ret = ctdb_req_control_pull(buf, buflen, &header, mem_ctx, &request);
3632 talloc_free(mem_ctx);
3633 tevent_req_error(req, ret);
3637 header_fix_pnn(&header, ctdb);
3639 if (header.destnode >= ctdb->node_map->num_nodes) {
3640 struct ctdb_reply_control reply;
3642 reply.rdata.opcode = request.opcode;
3643 reply.errmsg = "Invalid node";
3645 client_send_control(req, &header, &reply);
3649 DEBUG(DEBUG_INFO, ("request opcode = %u, reqid = %u\n",
3650 request.opcode, header.reqid));
3652 if (fake_control_failure(mem_ctx, req, &header, &request)) {
3656 switch (request.opcode) {
3657 case CTDB_CONTROL_PROCESS_EXISTS:
3658 control_process_exists(mem_ctx, req, &header, &request);
3661 case CTDB_CONTROL_PING:
3662 control_ping(mem_ctx, req, &header, &request);
3665 case CTDB_CONTROL_GETDBPATH:
3666 control_getdbpath(mem_ctx, req, &header, &request);
3669 case CTDB_CONTROL_GETVNNMAP:
3670 control_getvnnmap(mem_ctx, req, &header, &request);
3673 case CTDB_CONTROL_GET_DEBUG:
3674 control_get_debug(mem_ctx, req, &header, &request);
3677 case CTDB_CONTROL_SET_DEBUG:
3678 control_set_debug(mem_ctx, req, &header, &request);
3681 case CTDB_CONTROL_GET_DBMAP:
3682 control_get_dbmap(mem_ctx, req, &header, &request);
3685 case CTDB_CONTROL_GET_RECMODE:
3686 control_get_recmode(mem_ctx, req, &header, &request);
3689 case CTDB_CONTROL_SET_RECMODE:
3690 control_set_recmode(mem_ctx, req, &header, &request);
3693 case CTDB_CONTROL_DB_ATTACH:
3694 control_db_attach(mem_ctx, req, &header, &request);
3697 case CTDB_CONTROL_REGISTER_SRVID:
3698 control_register_srvid(mem_ctx, req, &header, &request);
3701 case CTDB_CONTROL_DEREGISTER_SRVID:
3702 control_deregister_srvid(mem_ctx, req, &header, &request);
3705 case CTDB_CONTROL_GET_DBNAME:
3706 control_get_dbname(mem_ctx, req, &header, &request);
3709 case CTDB_CONTROL_GET_PID:
3710 control_get_pid(mem_ctx, req, &header, &request);
3713 case CTDB_CONTROL_GET_RECMASTER:
3714 control_get_recmaster(mem_ctx, req, &header, &request);
3717 case CTDB_CONTROL_GET_PNN:
3718 control_get_pnn(mem_ctx, req, &header, &request);
3721 case CTDB_CONTROL_SHUTDOWN:
3722 control_shutdown(mem_ctx, req, &header, &request);
3725 case CTDB_CONTROL_SET_TUNABLE:
3726 control_set_tunable(mem_ctx, req, &header, &request);
3729 case CTDB_CONTROL_GET_TUNABLE:
3730 control_get_tunable(mem_ctx, req, &header, &request);
3733 case CTDB_CONTROL_LIST_TUNABLES:
3734 control_list_tunables(mem_ctx, req, &header, &request);
3737 case CTDB_CONTROL_MODIFY_FLAGS:
3738 control_modify_flags(mem_ctx, req, &header, &request);
3741 case CTDB_CONTROL_GET_ALL_TUNABLES:
3742 control_get_all_tunables(mem_ctx, req, &header, &request);
3745 case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
3746 control_db_attach_persistent(mem_ctx, req, &header, &request);
3749 case CTDB_CONTROL_UPTIME:
3750 control_uptime(mem_ctx, req, &header, &request);
3753 case CTDB_CONTROL_RELOAD_NODES_FILE:
3754 control_reload_nodes_file(mem_ctx, req, &header, &request);
3757 case CTDB_CONTROL_GET_CAPABILITIES:
3758 control_get_capabilities(mem_ctx, req, &header, &request);
3761 case CTDB_CONTROL_RELEASE_IP:
3762 control_release_ip(mem_ctx, req, &header, &request);
3765 case CTDB_CONTROL_TAKEOVER_IP:
3766 control_takeover_ip(mem_ctx, req, &header, &request);
3769 case CTDB_CONTROL_GET_PUBLIC_IPS:
3770 control_get_public_ips(mem_ctx, req, &header, &request);
3773 case CTDB_CONTROL_GET_NODEMAP:
3774 control_get_nodemap(mem_ctx, req, &header, &request);
3777 case CTDB_CONTROL_GET_RECLOCK_FILE:
3778 control_get_reclock_file(mem_ctx, req, &header, &request);
3781 case CTDB_CONTROL_STOP_NODE:
3782 control_stop_node(mem_ctx, req, &header, &request);
3785 case CTDB_CONTROL_CONTINUE_NODE:
3786 control_continue_node(mem_ctx, req, &header, &request);
3789 case CTDB_CONTROL_SET_BAN_STATE:
3790 control_set_ban_state(mem_ctx, req, &header, &request);
3793 case CTDB_CONTROL_GET_DB_SEQNUM:
3794 control_get_db_seqnum(mem_ctx, req, &header, &request);
3797 case CTDB_CONTROL_DB_GET_HEALTH:
3798 control_db_get_health(mem_ctx, req, &header, &request);
3801 case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
3802 control_get_public_ip_info(mem_ctx, req, &header, &request);
3805 case CTDB_CONTROL_GET_IFACES:
3806 control_get_ifaces(mem_ctx, req, &header, &request);
3809 case CTDB_CONTROL_SET_IFACE_LINK_STATE:
3810 control_set_iface_link_state(mem_ctx, req, &header, &request);
3813 case CTDB_CONTROL_SET_DB_READONLY:
3814 control_set_db_readonly(mem_ctx, req, &header, &request);
3817 case CTDB_CONTROL_SET_DB_STICKY:
3818 control_set_db_sticky(mem_ctx, req, &header, &request);
3821 case CTDB_CONTROL_IPREALLOCATED:
3822 control_ipreallocated(mem_ctx, req, &header, &request);
3825 case CTDB_CONTROL_GET_RUNSTATE:
3826 control_get_runstate(mem_ctx, req, &header, &request);
3829 case CTDB_CONTROL_GET_NODES_FILE:
3830 control_get_nodes_file(mem_ctx, req, &header, &request);
3833 case CTDB_CONTROL_DB_OPEN_FLAGS:
3834 control_db_open_flags(mem_ctx, req, &header, &request);
3837 case CTDB_CONTROL_DB_ATTACH_REPLICATED:
3838 control_db_attach_replicated(mem_ctx, req, &header, &request);
3841 case CTDB_CONTROL_CHECK_PID_SRVID:
3842 control_check_pid_srvid(mem_ctx, req, &header, &request);
3846 if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) {
3847 control_error(mem_ctx, req, &header, &request);
3853 talloc_free(mem_ctx);
3856 static int client_recv(struct tevent_req *req, int *perr)
3858 struct client_state *state = tevent_req_data(
3859 req, struct client_state);
3862 DEBUG(DEBUG_INFO, ("Client done fd=%d\n", state->fd));
3865 if (tevent_req_is_unix_error(req, &err)) {
3872 return state->status;
3879 struct server_state {
3880 struct tevent_context *ev;
3881 struct ctdbd_context *ctdb;
3885 static void server_new_client(struct tevent_req *subreq);
3886 static void server_client_done(struct tevent_req *subreq);
3888 static struct tevent_req *server_send(TALLOC_CTX *mem_ctx,
3889 struct tevent_context *ev,
3890 struct ctdbd_context *ctdb,
3893 struct tevent_req *req, *subreq;
3894 struct server_state *state;
3896 req = tevent_req_create(mem_ctx, &state, struct server_state);
3905 subreq = accept_send(state, ev, fd);
3906 if (tevent_req_nomem(subreq, req)) {
3907 return tevent_req_post(req, ev);
3909 tevent_req_set_callback(subreq, server_new_client, req);
3914 static void server_new_client(struct tevent_req *subreq)
3916 struct tevent_req *req = tevent_req_callback_data(
3917 subreq, struct tevent_req);
3918 struct server_state *state = tevent_req_data(
3919 req, struct server_state);
3920 struct ctdbd_context *ctdb = state->ctdb;
3924 client_fd = accept_recv(subreq, NULL, NULL, &ret);
3925 TALLOC_FREE(subreq);
3926 if (client_fd == -1) {
3927 tevent_req_error(req, ret);
3931 subreq = client_send(state, state->ev, client_fd,
3932 ctdb, ctdb->node_map->pnn);
3933 if (tevent_req_nomem(subreq, req)) {
3936 tevent_req_set_callback(subreq, server_client_done, req);
3938 ctdb->num_clients += 1;
3940 subreq = accept_send(state, state->ev, state->fd);
3941 if (tevent_req_nomem(subreq, req)) {
3944 tevent_req_set_callback(subreq, server_new_client, req);
3947 static void server_client_done(struct tevent_req *subreq)
3949 struct tevent_req *req = tevent_req_callback_data(
3950 subreq, struct tevent_req);
3951 struct server_state *state = tevent_req_data(
3952 req, struct server_state);
3953 struct ctdbd_context *ctdb = state->ctdb;
3957 status = client_recv(subreq, &ret);
3958 TALLOC_FREE(subreq);
3960 tevent_req_error(req, ret);
3964 ctdb->num_clients -= 1;
3967 /* Special status, to shutdown server */
3968 DEBUG(DEBUG_INFO, ("Shutting down server\n"));
3969 tevent_req_done(req);
3973 static bool server_recv(struct tevent_req *req, int *perr)
3977 if (tevent_req_is_unix_error(req, &err)) {
3990 static int socket_init(const char *sockpath)
3992 struct sockaddr_un addr;
3996 memset(&addr, 0, sizeof(addr));
3997 addr.sun_family = AF_UNIX;
3999 len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
4000 if (len >= sizeof(addr.sun_path)) {
4001 fprintf(stderr, "path too long: %s\n", sockpath);
4005 fd = socket(AF_UNIX, SOCK_STREAM, 0);
4007 fprintf(stderr, "socket failed - %s\n", sockpath);
4011 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
4013 fprintf(stderr, "bind failed - %s\n", sockpath);
4017 ret = listen(fd, 10);
4019 fprintf(stderr, "listen failed\n");
4023 DEBUG(DEBUG_INFO, ("Socket init done\n"));
4034 static struct options {
4036 const char *sockpath;
4037 const char *pidfile;
4038 const char *debuglevel;
4041 static struct poptOption cmdline_options[] = {
4043 { "dbdir", 'D', POPT_ARG_STRING, &options.dbdir, 0,
4044 "Database directory", "directory" },
4045 { "socket", 's', POPT_ARG_STRING, &options.sockpath, 0,
4046 "Unix domain socket path", "filename" },
4047 { "pidfile", 'p', POPT_ARG_STRING, &options.pidfile, 0,
4048 "pid file", "filename" } ,
4049 { "debug", 'd', POPT_ARG_STRING, &options.debuglevel, 0,
4050 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
4054 static void cleanup(void)
4056 unlink(options.sockpath);
4057 unlink(options.pidfile);
4060 static void signal_handler(int sig)
4066 static void start_server(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
4067 struct ctdbd_context *ctdb, int fd, int pfd)
4069 struct tevent_req *req;
4074 signal(SIGTERM, signal_handler);
4076 req = server_send(mem_ctx, ev, ctdb, fd);
4078 fprintf(stderr, "Memory error\n");
4082 len = write(pfd, &ret, sizeof(ret));
4083 if (len != sizeof(ret)) {
4084 fprintf(stderr, "Failed to send message to parent\n");
4089 tevent_req_poll(req, ev);
4091 server_recv(req, &ret);
4097 int main(int argc, const char *argv[])
4099 TALLOC_CTX *mem_ctx;
4100 struct ctdbd_context *ctdb;
4101 struct tevent_context *ev;
4103 int opt, fd, ret, pfd[2];
4108 pc = poptGetContext(argv[0], argc, argv, cmdline_options,
4109 POPT_CONTEXT_KEEP_FIRST);
4110 while ((opt = poptGetNextOpt(pc)) != -1) {
4111 fprintf(stderr, "Invalid option %s\n", poptBadOption(pc, 0));
4115 if (options.dbdir == NULL) {
4116 fprintf(stderr, "Please specify database directory\n");
4117 poptPrintHelp(pc, stdout, 0);
4121 if (options.sockpath == NULL) {
4122 fprintf(stderr, "Please specify socket path\n");
4123 poptPrintHelp(pc, stdout, 0);
4127 if (options.pidfile == NULL) {
4128 fprintf(stderr, "Please specify pid file\n");
4129 poptPrintHelp(pc, stdout, 0);
4133 mem_ctx = talloc_new(NULL);
4134 if (mem_ctx == NULL) {
4135 fprintf(stderr, "Memory error\n");
4139 ret = logging_init(mem_ctx, "file:", options.debuglevel, "fake-ctdbd");
4141 fprintf(stderr, "Invalid debug level\n");
4142 poptPrintHelp(pc, stdout, 0);
4146 ctdb = ctdbd_setup(mem_ctx, options.dbdir);
4151 if (! ctdbd_verify(ctdb)) {
4155 ev = tevent_context_init(mem_ctx);
4157 fprintf(stderr, "Memory error\n");
4161 fd = socket_init(options.sockpath);
4168 fprintf(stderr, "Failed to create pipe\n");
4175 fprintf(stderr, "Failed to fork\n");
4183 start_server(mem_ctx, ev, ctdb, fd, pfd[1]);
4190 len = read(pfd[0], &ret, sizeof(ret));
4192 if (len != sizeof(ret)) {
4193 fprintf(stderr, "len = %zi\n", len);
4194 fprintf(stderr, "Failed to get message from child\n");
4199 fp = fopen(options.pidfile, "w");
4201 fprintf(stderr, "Failed to open pid file %s\n",
4206 fprintf(fp, "%d\n", pid);