2 Fake CTDB server for testing
4 Copyright (C) Amitay Isaacs 2016
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/network.h"
22 #include "system/time.h"
29 #include "lib/util/dlinklist.h"
30 #include "lib/util/tevent_unix.h"
31 #include "lib/util/debug.h"
32 #include "lib/util/samba_util.h"
33 #include "lib/async_req/async_sock.h"
35 #include "protocol/protocol.h"
36 #include "protocol/protocol_api.h"
38 #include "common/comm.h"
39 #include "common/system.h"
40 #include "common/logging.h"
41 #include "common/tunable.h"
42 #include "common/srvid.h"
44 #include "ipalloc_read_known_ips.h"
47 #define CTDB_PORT 4379
49 /* A fake flag that is only supported by some functions */
50 #define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
56 uint32_t capabilities
;
57 bool recovery_disabled
;
58 void *recovery_substate
;
74 struct interface_map
{
76 struct interface
*iface
;
98 struct fake_control_failure
{
99 struct fake_control_failure
*prev
, *next
;
100 enum ctdb_controls opcode
;
107 struct ctdb_client
*prev
, *next
;
108 struct ctdbd_context
*ctdb
;
113 struct ctdbd_context
{
114 struct node_map
*node_map
;
115 struct interface_map
*iface_map
;
116 struct vnn_map
*vnn_map
;
117 struct database_map
*db_map
;
118 struct srvid_context
*srv
;
120 struct timeval start_time
;
121 struct timeval recovery_start_time
;
122 struct timeval recovery_end_time
;
123 bool takeover_disabled
;
125 enum ctdb_runstate runstate
;
126 struct ctdb_tunable_list tun_list
;
129 struct ctdb_public_ip_list
*known_ips
;
130 struct fake_control_failure
*control_failures
;
131 struct ctdb_client
*client_list
;
138 static struct node_map
*nodemap_init(TALLOC_CTX
*mem_ctx
)
140 struct node_map
*node_map
;
142 node_map
= talloc_zero(mem_ctx
, struct node_map
);
143 if (node_map
== NULL
) {
147 node_map
->pnn
= CTDB_UNKNOWN_PNN
;
148 node_map
->recmaster
= CTDB_UNKNOWN_PNN
;
153 /* Read a nodemap from stdin. Each line looks like:
154 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
155 * EOF or a blank line terminates input.
157 * By default, capablities for each node are
158 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER. These 2
159 * capabilities can be faked off by adding, for example,
160 * -CTDB_CAP_RECMASTER.
163 static bool nodemap_parse(struct node_map
*node_map
)
167 while ((fgets(line
, sizeof(line
), stdin
) != NULL
)) {
168 uint32_t pnn
, flags
, capabilities
;
171 ctdb_sock_addr saddr
;
174 if (line
[0] == '\n') {
178 /* Get rid of pesky newline */
179 if ((t
= strchr(line
, '\n')) != NULL
) {
184 tok
= strtok(line
, " \t");
186 fprintf(stderr
, "bad line (%s) - missing PNN\n", line
);
189 pnn
= (uint32_t)strtoul(tok
, NULL
, 0);
192 tok
= strtok(NULL
, " \t");
194 fprintf(stderr
, "bad line (%s) - missing IP\n", line
);
197 if (!parse_ip(tok
, NULL
, CTDB_PORT
, &saddr
)) {
198 fprintf(stderr
, "bad line (%s) - invalid IP\n", line
);
201 ip
= talloc_strdup(node_map
, tok
);
207 tok
= strtok(NULL
, " \t");
209 fprintf(stderr
, "bad line (%s) - missing flags\n",
213 flags
= (uint32_t)strtoul(tok
, NULL
, 0);
214 /* Handle deleted nodes */
215 if (flags
& NODE_FLAGS_DELETED
) {
217 ip
= talloc_strdup(node_map
, "0.0.0.0");
222 capabilities
= CTDB_CAP_RECMASTER
|CTDB_CAP_LMASTER
;
224 tok
= strtok(NULL
, " \t");
225 while (tok
!= NULL
) {
226 if (strcmp(tok
, "CURRENT") == 0) {
228 } else if (strcmp(tok
, "RECMASTER") == 0) {
229 node_map
->recmaster
= pnn
;
230 } else if (strcmp(tok
, "-CTDB_CAP_RECMASTER") == 0) {
231 capabilities
&= ~CTDB_CAP_RECMASTER
;
232 } else if (strcmp(tok
, "-CTDB_CAP_LMASTER") == 0) {
233 capabilities
&= ~CTDB_CAP_LMASTER
;
234 } else if (strcmp(tok
, "TIMEOUT") == 0) {
235 /* This can be done with just a flag
236 * value but it is probably clearer
237 * and less error-prone to fake this
238 * with an explicit token */
239 flags
|= NODE_FLAGS_FAKE_TIMEOUT
;
241 tok
= strtok(NULL
, " \t");
244 node_map
->node
= talloc_realloc(node_map
, node_map
->node
,
246 node_map
->num_nodes
+ 1);
247 if (node_map
->node
== NULL
) {
250 node
= &node_map
->node
[node_map
->num_nodes
];
252 parse_ip(ip
, NULL
, CTDB_PORT
, &node
->addr
);
255 node
->capabilities
= capabilities
;
256 node
->recovery_disabled
= false;
257 node
->recovery_substate
= NULL
;
259 node_map
->num_nodes
+= 1;
262 DEBUG(DEBUG_INFO
, ("Parsing nodemap done\n"));
266 DEBUG(DEBUG_INFO
, ("Parsing nodemap failed\n"));
271 /* Append a node to a node map with given address and flags */
272 static bool node_map_add(struct ctdb_node_map
*nodemap
,
273 const char *nstr
, uint32_t flags
)
277 struct ctdb_node_and_flags
*n
;
279 if (! parse_ip(nstr
, NULL
, CTDB_PORT
, &addr
)) {
280 fprintf(stderr
, "Invalid IP address %s\n", nstr
);
285 nodemap
->node
= talloc_realloc(nodemap
, nodemap
->node
,
286 struct ctdb_node_and_flags
, num
+1);
287 if (nodemap
->node
== NULL
) {
291 n
= &nodemap
->node
[num
];
296 nodemap
->num
= num
+1;
300 /* Read a nodes file into a node map */
301 static struct ctdb_node_map
*ctdb_read_nodes_file(TALLOC_CTX
*mem_ctx
,
307 struct ctdb_node_map
*nodemap
;
309 nodemap
= talloc_zero(mem_ctx
, struct ctdb_node_map
);
310 if (nodemap
== NULL
) {
314 lines
= file_lines_load(nlist
, &nlines
, 0, mem_ctx
);
319 while (nlines
> 0 && strcmp(lines
[nlines
-1], "") == 0) {
323 for (i
=0; i
<nlines
; i
++) {
329 /* strip leading spaces */
330 while((*node
== ' ') || (*node
== '\t')) {
336 /* strip trailing spaces */
338 ((node
[len
-1] == ' ') || (node
[len
-1] == '\t')))
348 /* A "deleted" node is a node that is
349 commented out in the nodes file. This is
350 used instead of removing a line, which
351 would cause subsequent nodes to change
353 flags
= NODE_FLAGS_DELETED
;
354 node
= discard_const("0.0.0.0");
358 if (! node_map_add(nodemap
, node
, flags
)) {
360 TALLOC_FREE(nodemap
);
369 static struct ctdb_node_map
*read_nodes_file(TALLOC_CTX
*mem_ctx
,
372 struct ctdb_node_map
*nodemap
;
373 char nodepath
[PATH_MAX
];
374 const char *nodes_list
;
376 /* read the nodes file */
377 sprintf(nodepath
, "CTDB_NODES_%u", pnn
);
378 nodes_list
= getenv(nodepath
);
379 if (nodes_list
== NULL
) {
380 nodes_list
= getenv("CTDB_NODES");
381 if (nodes_list
== NULL
) {
382 DEBUG(DEBUG_INFO
, ("Nodes file not defined\n"));
387 nodemap
= ctdb_read_nodes_file(mem_ctx
, nodes_list
);
388 if (nodemap
== NULL
) {
389 DEBUG(DEBUG_INFO
, ("Failed to read nodes file \"%s\"\n",
397 static struct interface_map
*interfaces_init(TALLOC_CTX
*mem_ctx
)
399 struct interface_map
*iface_map
;
401 iface_map
= talloc_zero(mem_ctx
, struct interface_map
);
402 if (iface_map
== NULL
) {
409 /* Read interfaces information. Same format as "ctdb ifaces -Y"
411 * :Name:LinkStatus:References:
416 static bool interfaces_parse(struct interface_map
*iface_map
)
420 while ((fgets(line
, sizeof(line
), stdin
) != NULL
)) {
423 char *tok
, *t
, *name
;
424 struct interface
*iface
;
426 if (line
[0] == '\n') {
430 /* Get rid of pesky newline */
431 if ((t
= strchr(line
, '\n')) != NULL
) {
435 if (strcmp(line
, ":Name:LinkStatus:References:") == 0) {
439 /* Leading colon... */
440 // tok = strtok(line, ":");
443 tok
= strtok(line
, ":");
445 fprintf(stderr
, "bad line (%s) - missing name\n", line
);
451 tok
= strtok(NULL
, ":");
453 fprintf(stderr
, "bad line (%s) - missing link state\n",
457 link_state
= (uint16_t)strtoul(tok
, NULL
, 0);
460 tok
= strtok(NULL
, ":");
462 fprintf(stderr
, "bad line (%s) - missing references\n",
466 references
= (uint32_t)strtoul(tok
, NULL
, 0);
468 iface_map
->iface
= talloc_realloc(iface_map
, iface_map
->iface
,
471 if (iface_map
->iface
== NULL
) {
475 iface
= &iface_map
->iface
[iface_map
->num
];
477 iface
->name
= talloc_strdup(iface_map
, name
);
478 if (iface
->name
== NULL
) {
481 iface
->link_up
= link_state
;
482 iface
->references
= references
;
487 DEBUG(DEBUG_INFO
, ("Parsing interfaces done\n"));
491 fprintf(stderr
, "Parsing interfaces failed\n");
495 static struct vnn_map
*vnnmap_init(TALLOC_CTX
*mem_ctx
)
497 struct vnn_map
*vnn_map
;
499 vnn_map
= talloc_zero(mem_ctx
, struct vnn_map
);
500 if (vnn_map
== NULL
) {
501 fprintf(stderr
, "Memory error\n");
504 vnn_map
->recmode
= CTDB_RECOVERY_ACTIVE
;
505 vnn_map
->generation
= INVALID_GENERATION
;
518 static bool vnnmap_parse(struct vnn_map
*vnn_map
)
522 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
526 if (line
[0] == '\n') {
530 /* Get rid of pesky newline */
531 if ((t
= strchr(line
, '\n')) != NULL
) {
535 n
= (uint32_t) strtol(line
, NULL
, 0);
538 if (vnn_map
->generation
== INVALID_GENERATION
) {
539 vnn_map
->generation
= n
;
543 vnn_map
->map
= talloc_realloc(vnn_map
, vnn_map
->map
, uint32_t,
545 if (vnn_map
->map
== NULL
) {
546 fprintf(stderr
, "Memory error\n");
550 vnn_map
->map
[vnn_map
->size
] = n
;
554 DEBUG(DEBUG_INFO
, ("Parsing vnnmap done\n"));
558 fprintf(stderr
, "Parsing vnnmap failed\n");
562 static bool reclock_parse(struct ctdbd_context
*ctdb
)
567 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
571 if (line
[0] == '\n') {
572 /* Recovery lock remains unset */
576 /* Get rid of pesky newline */
577 if ((t
= strchr(line
, '\n')) != NULL
) {
581 ctdb
->reclock
= talloc_strdup(ctdb
, line
);
582 if (ctdb
->reclock
== NULL
) {
586 /* Swallow possible blank line following section. Picky
587 * compiler settings don't allow the return value to be
588 * ignored, so make the compiler happy.
590 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
593 DEBUG(DEBUG_INFO
, ("Parsing reclock done\n"));
597 fprintf(stderr
, "Parsing reclock failed\n");
601 static struct database_map
*dbmap_init(TALLOC_CTX
*mem_ctx
)
603 struct database_map
*db_map
;
605 db_map
= talloc_zero(mem_ctx
, struct database_map
);
606 if (db_map
== NULL
) {
613 /* Read a database map from stdin. Each line looks like:
614 * <ID> <NAME> [FLAGS] [SEQ_NUM]
615 * EOF or a blank line terminates input.
617 * By default, flags and seq_num are 0
620 static bool dbmap_parse(struct database_map
*db_map
)
624 while ((fgets(line
, sizeof(line
), stdin
) != NULL
)) {
627 uint32_t seq_num
= 0;
632 if (line
[0] == '\n') {
636 /* Get rid of pesky newline */
637 if ((t
= strchr(line
, '\n')) != NULL
) {
642 tok
= strtok(line
, " \t");
644 fprintf(stderr
, "bad line (%s) - missing ID\n", line
);
647 id
= (uint32_t)strtoul(tok
, NULL
, 0);
650 tok
= strtok(NULL
, " \t");
652 fprintf(stderr
, "bad line (%s) - missing NAME\n", line
);
655 name
= talloc_strdup(db_map
, tok
);
661 tok
= strtok(NULL
, " \t");
662 while (tok
!= NULL
) {
663 if (strcmp(tok
, "PERSISTENT") == 0) {
664 flags
|= CTDB_DB_FLAGS_PERSISTENT
;
665 } else if (strcmp(tok
, "STICKY") == 0) {
666 flags
|= CTDB_DB_FLAGS_STICKY
;
667 } else if (strcmp(tok
, "READONLY") == 0) {
668 flags
|= CTDB_DB_FLAGS_READONLY
;
669 } else if (strcmp(tok
, "REPLICATED") == 0) {
670 flags
|= CTDB_DB_FLAGS_REPLICATED
;
671 } else if (tok
[0] >= '0'&& tok
[0] <= '9') {
672 uint8_t nv
= CTDB_DB_FLAGS_PERSISTENT
|
673 CTDB_DB_FLAGS_REPLICATED
;
675 if ((flags
& nv
) == 0) {
677 "seq_num for volatile db\n");
680 seq_num
= (uint64_t)strtoull(tok
, NULL
, 0);
683 tok
= strtok(NULL
, " \t");
686 db_map
->db
= talloc_realloc(db_map
, db_map
->db
,
688 db_map
->num_dbs
+ 1);
689 if (db_map
->db
== NULL
) {
692 db
= &db_map
->db
[db_map
->num_dbs
];
697 db
->seq_num
= seq_num
;
699 db_map
->num_dbs
+= 1;
702 DEBUG(DEBUG_INFO
, ("Parsing dbmap done\n"));
706 DEBUG(DEBUG_INFO
, ("Parsing dbmap failed\n"));
711 static struct database
*database_find(struct database_map
*map
,
716 for (i
= 0; i
< map
->num_dbs
; i
++) {
717 struct database
*db
= &map
->db
[i
];
719 if (db
->id
== db_id
) {
727 static bool public_ips_parse(struct ctdbd_context
*ctdb
,
731 D_ERR("Must initialise nodemap before public IPs\n");
735 ctdb
->known_ips
= ipalloc_read_known_ips(ctdb
, numnodes
, false);
737 return (ctdb
->known_ips
!= NULL
);
740 /* Read information about controls to fail. Format is:
741 * <opcode> <pnn> {ERROR|TIMEOUT} <comment>
743 static bool control_failures_parse(struct ctdbd_context
*ctdb
)
747 while ((fgets(line
, sizeof(line
), stdin
) != NULL
)) {
749 enum ctdb_controls opcode
;
753 struct fake_control_failure
*failure
= NULL
;
755 if (line
[0] == '\n') {
759 /* Get rid of pesky newline */
760 if ((t
= strchr(line
, '\n')) != NULL
) {
765 tok
= strtok(line
, " \t");
767 D_ERR("bad line (%s) - missing opcode\n", line
);
770 opcode
= (enum ctdb_controls
)strtoul(tok
, NULL
, 0);
773 tok
= strtok(NULL
, " \t");
775 D_ERR("bad line (%s) - missing PNN\n", line
);
778 pnn
= (uint32_t)strtoul(tok
, NULL
, 0);
781 tok
= strtok(NULL
, " \t");
783 D_ERR("bad line (%s) - missing errno\n", line
);
786 error
= talloc_strdup(ctdb
, tok
);
790 if (strcmp(error
, "ERROR") != 0 &&
791 strcmp(error
, "TIMEOUT") != 0) {
792 D_ERR("bad line (%s) "
793 "- error must be \"ERROR\" or \"TIMEOUT\"\n",
799 tok
= strtok(NULL
, "\n"); /* rest of line */
801 D_ERR("bad line (%s) - missing comment\n", line
);
804 comment
= talloc_strdup(ctdb
, tok
);
805 if (comment
== NULL
) {
809 failure
= talloc_zero(ctdb
, struct fake_control_failure
);
810 if (failure
== NULL
) {
814 failure
->opcode
= opcode
;
816 failure
->error
= error
;
817 failure
->comment
= comment
;
819 DLIST_ADD(ctdb
->control_failures
, failure
);
822 D_INFO("Parsing fake control failures done\n");
826 D_INFO("Parsing fake control failures failed\n");
834 static int ctdb_client_destructor(struct ctdb_client
*client
)
836 DLIST_REMOVE(client
->ctdb
->client_list
, client
);
840 static int client_add(struct ctdbd_context
*ctdb
, pid_t client_pid
,
843 struct ctdb_client
*client
;
845 client
= talloc_zero(client_state
, struct ctdb_client
);
846 if (client
== NULL
) {
851 client
->pid
= client_pid
;
852 client
->state
= client_state
;
854 DLIST_ADD(ctdb
->client_list
, client
);
855 talloc_set_destructor(client
, ctdb_client_destructor
);
859 static void *client_find(struct ctdbd_context
*ctdb
, pid_t client_pid
)
861 struct ctdb_client
*client
;
863 for (client
=ctdb
->client_list
; client
!= NULL
; client
=client
->next
) {
864 if (client
->pid
== client_pid
) {
865 return client
->state
;
876 static uint32_t new_generation(uint32_t old_generation
)
881 generation
= random();
882 if (generation
!= INVALID_GENERATION
&&
883 generation
!= old_generation
) {
891 static struct ctdbd_context
*ctdbd_setup(TALLOC_CTX
*mem_ctx
)
893 struct ctdbd_context
*ctdb
;
898 ctdb
= talloc_zero(mem_ctx
, struct ctdbd_context
);
903 ctdb
->node_map
= nodemap_init(ctdb
);
904 if (ctdb
->node_map
== NULL
) {
908 ctdb
->iface_map
= interfaces_init(ctdb
);
909 if (ctdb
->iface_map
== NULL
) {
913 ctdb
->vnn_map
= vnnmap_init(ctdb
);
914 if (ctdb
->vnn_map
== NULL
) {
918 ctdb
->db_map
= dbmap_init(ctdb
);
919 if (ctdb
->db_map
== NULL
) {
923 ret
= srvid_init(ctdb
, &ctdb
->srv
);
928 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
931 if ((t
= strchr(line
, '\n')) != NULL
) {
935 if (strcmp(line
, "NODEMAP") == 0) {
936 status
= nodemap_parse(ctdb
->node_map
);
937 } else if (strcmp(line
, "IFACES") == 0) {
938 status
= interfaces_parse(ctdb
->iface_map
);
939 } else if (strcmp(line
, "VNNMAP") == 0) {
940 status
= vnnmap_parse(ctdb
->vnn_map
);
941 } else if (strcmp(line
, "DBMAP") == 0) {
942 status
= dbmap_parse(ctdb
->db_map
);
943 } else if (strcmp(line
, "PUBLICIPS") == 0) {
944 status
= public_ips_parse(ctdb
,
945 ctdb
->node_map
->num_nodes
);
946 } else if (strcmp(line
, "RECLOCK") == 0) {
947 status
= reclock_parse(ctdb
);
948 } else if (strcmp(line
, "CONTROLFAILS") == 0) {
949 status
= control_failures_parse(ctdb
);
951 fprintf(stderr
, "Unknown line %s\n", line
);
960 ctdb
->start_time
= tevent_timeval_current();
961 ctdb
->recovery_start_time
= tevent_timeval_current();
962 ctdb
->vnn_map
->recmode
= CTDB_RECOVERY_NORMAL
;
963 if (ctdb
->vnn_map
->generation
== INVALID_GENERATION
) {
964 ctdb
->vnn_map
->generation
=
965 new_generation(ctdb
->vnn_map
->generation
);
967 ctdb
->recovery_end_time
= tevent_timeval_current();
969 ctdb
->log_level
= DEBUG_ERR
;
970 ctdb
->runstate
= CTDB_RUNSTATE_RUNNING
;
972 ctdb_tunable_set_defaults(&ctdb
->tun_list
);
974 ctdb
->monitoring_mode
= CTDB_MONITORING_ENABLED
;
983 static bool ctdbd_verify(struct ctdbd_context
*ctdb
)
988 if (ctdb
->node_map
->num_nodes
== 0) {
992 /* Make sure all the nodes are in order */
993 for (i
=0; i
<ctdb
->node_map
->num_nodes
; i
++) {
994 node
= &ctdb
->node_map
->node
[i
];
995 if (node
->pnn
!= i
) {
996 fprintf(stderr
, "Expected node %u, found %u\n",
1002 node
= &ctdb
->node_map
->node
[ctdb
->node_map
->pnn
];
1003 if (node
->flags
& NODE_FLAGS_DISCONNECTED
) {
1004 DEBUG(DEBUG_INFO
, ("Node disconnected, exiting\n"));
1015 struct recover_state
{
1016 struct tevent_context
*ev
;
1017 struct ctdbd_context
*ctdb
;
1020 static int recover_check(struct tevent_req
*req
);
1021 static void recover_wait_done(struct tevent_req
*subreq
);
1022 static void recover_done(struct tevent_req
*subreq
);
1024 static struct tevent_req
*recover_send(TALLOC_CTX
*mem_ctx
,
1025 struct tevent_context
*ev
,
1026 struct ctdbd_context
*ctdb
)
1028 struct tevent_req
*req
;
1029 struct recover_state
*state
;
1032 req
= tevent_req_create(mem_ctx
, &state
, struct recover_state
);
1040 ret
= recover_check(req
);
1042 tevent_req_error(req
, ret
);
1043 return tevent_req_post(req
, ev
);
1049 static int recover_check(struct tevent_req
*req
)
1051 struct recover_state
*state
= tevent_req_data(
1052 req
, struct recover_state
);
1053 struct ctdbd_context
*ctdb
= state
->ctdb
;
1054 struct tevent_req
*subreq
;
1055 bool recovery_disabled
;
1058 recovery_disabled
= false;
1059 for (i
=0; i
<ctdb
->node_map
->num_nodes
; i
++) {
1060 if (ctdb
->node_map
->node
[i
].recovery_disabled
) {
1061 recovery_disabled
= true;
1066 subreq
= tevent_wakeup_send(state
, state
->ev
,
1067 tevent_timeval_current_ofs(1, 0));
1068 if (subreq
== NULL
) {
1072 if (recovery_disabled
) {
1073 tevent_req_set_callback(subreq
, recover_wait_done
, req
);
1075 ctdb
->recovery_start_time
= tevent_timeval_current();
1076 tevent_req_set_callback(subreq
, recover_done
, req
);
1082 static void recover_wait_done(struct tevent_req
*subreq
)
1084 struct tevent_req
*req
= tevent_req_callback_data(
1085 subreq
, struct tevent_req
);
1089 status
= tevent_wakeup_recv(subreq
);
1090 TALLOC_FREE(subreq
);
1092 tevent_req_error(req
, EIO
);
1096 ret
= recover_check(req
);
1098 tevent_req_error(req
, ret
);
1102 static void recover_done(struct tevent_req
*subreq
)
1104 struct tevent_req
*req
= tevent_req_callback_data(
1105 subreq
, struct tevent_req
);
1106 struct recover_state
*state
= tevent_req_data(
1107 req
, struct recover_state
);
1108 struct ctdbd_context
*ctdb
= state
->ctdb
;
1111 status
= tevent_wakeup_recv(subreq
);
1112 TALLOC_FREE(subreq
);
1114 tevent_req_error(req
, EIO
);
1118 ctdb
->vnn_map
->recmode
= CTDB_RECOVERY_NORMAL
;
1119 ctdb
->recovery_end_time
= tevent_timeval_current();
1120 ctdb
->vnn_map
->generation
= new_generation(ctdb
->vnn_map
->generation
);
1122 tevent_req_done(req
);
1125 static bool recover_recv(struct tevent_req
*req
, int *perr
)
1129 if (tevent_req_is_unix_error(req
, &err
)) {
1140 * Routines for ctdb_req_header
1143 static void header_fix_pnn(struct ctdb_req_header
*header
,
1144 struct ctdbd_context
*ctdb
)
1146 if (header
->srcnode
== CTDB_CURRENT_NODE
) {
1147 header
->srcnode
= ctdb
->node_map
->pnn
;
1150 if (header
->destnode
== CTDB_CURRENT_NODE
) {
1151 header
->destnode
= ctdb
->node_map
->pnn
;
1155 static struct ctdb_req_header
header_reply_control(
1156 struct ctdb_req_header
*header
,
1157 struct ctdbd_context
*ctdb
)
1159 struct ctdb_req_header reply_header
;
1161 reply_header
= (struct ctdb_req_header
) {
1162 .ctdb_magic
= CTDB_MAGIC
,
1163 .ctdb_version
= CTDB_PROTOCOL
,
1164 .generation
= ctdb
->vnn_map
->generation
,
1165 .operation
= CTDB_REPLY_CONTROL
,
1166 .destnode
= header
->srcnode
,
1167 .srcnode
= header
->destnode
,
1168 .reqid
= header
->reqid
,
1171 return reply_header
;
1174 static struct ctdb_req_header
header_reply_message(
1175 struct ctdb_req_header
*header
,
1176 struct ctdbd_context
*ctdb
)
1178 struct ctdb_req_header reply_header
;
1180 reply_header
= (struct ctdb_req_header
) {
1181 .ctdb_magic
= CTDB_MAGIC
,
1182 .ctdb_version
= CTDB_PROTOCOL
,
1183 .generation
= ctdb
->vnn_map
->generation
,
1184 .operation
= CTDB_REQ_MESSAGE
,
1185 .destnode
= header
->srcnode
,
1186 .srcnode
= header
->destnode
,
1190 return reply_header
;
1197 struct client_state
{
1198 struct tevent_context
*ev
;
1200 struct ctdbd_context
*ctdb
;
1203 struct comm_context
*comm
;
1204 struct srvid_register_state
*rstate
;
1209 * Send replies to controls and messages
1212 static void client_reply_done(struct tevent_req
*subreq
);
1214 static void client_send_message(struct tevent_req
*req
,
1215 struct ctdb_req_header
*header
,
1216 struct ctdb_req_message_data
*message
)
1218 struct client_state
*state
= tevent_req_data(
1219 req
, struct client_state
);
1220 struct ctdbd_context
*ctdb
= state
->ctdb
;
1221 struct tevent_req
*subreq
;
1222 struct ctdb_req_header reply_header
;
1224 size_t datalen
, buflen
;
1227 reply_header
= header_reply_message(header
, ctdb
);
1229 datalen
= ctdb_req_message_data_len(&reply_header
, message
);
1230 ret
= ctdb_allocate_pkt(state
, datalen
, &buf
, &buflen
);
1232 tevent_req_error(req
, ret
);
1236 ret
= ctdb_req_message_data_push(&reply_header
, message
,
1239 tevent_req_error(req
, ret
);
1243 DEBUG(DEBUG_INFO
, ("message srvid = 0x%"PRIx64
"\n", message
->srvid
));
1245 subreq
= comm_write_send(state
, state
->ev
, state
->comm
, buf
, buflen
);
1246 if (tevent_req_nomem(subreq
, req
)) {
1249 tevent_req_set_callback(subreq
, client_reply_done
, req
);
1251 talloc_steal(subreq
, buf
);
1254 static void client_send_control(struct tevent_req
*req
,
1255 struct ctdb_req_header
*header
,
1256 struct ctdb_reply_control
*reply
)
1258 struct client_state
*state
= tevent_req_data(
1259 req
, struct client_state
);
1260 struct ctdbd_context
*ctdb
= state
->ctdb
;
1261 struct tevent_req
*subreq
;
1262 struct ctdb_req_header reply_header
;
1264 size_t datalen
, buflen
;
1267 reply_header
= header_reply_control(header
, ctdb
);
1269 datalen
= ctdb_reply_control_len(&reply_header
, reply
);
1270 ret
= ctdb_allocate_pkt(state
, datalen
, &buf
, &buflen
);
1272 tevent_req_error(req
, ret
);
1276 ret
= ctdb_reply_control_push(&reply_header
, reply
, buf
, &buflen
);
1278 tevent_req_error(req
, ret
);
1282 DEBUG(DEBUG_INFO
, ("reply opcode = %u\n", reply
->rdata
.opcode
));
1284 subreq
= comm_write_send(state
, state
->ev
, state
->comm
, buf
, buflen
);
1285 if (tevent_req_nomem(subreq
, req
)) {
1288 tevent_req_set_callback(subreq
, client_reply_done
, req
);
1290 talloc_steal(subreq
, buf
);
1293 static void client_reply_done(struct tevent_req
*subreq
)
1295 struct tevent_req
*req
= tevent_req_callback_data(
1296 subreq
, struct tevent_req
);
1300 status
= comm_write_recv(subreq
, &ret
);
1301 TALLOC_FREE(subreq
);
1303 tevent_req_error(req
, ret
);
1308 * Handling protocol - controls
1311 static void control_process_exists(TALLOC_CTX
*mem_ctx
,
1312 struct tevent_req
*req
,
1313 struct ctdb_req_header
*header
,
1314 struct ctdb_req_control
*request
)
1316 struct client_state
*state
= tevent_req_data(
1317 req
, struct client_state
);
1318 struct ctdbd_context
*ctdb
= state
->ctdb
;
1319 struct client_state
*cstate
;
1320 struct ctdb_reply_control reply
;
1322 reply
.rdata
.opcode
= request
->opcode
;
1324 cstate
= client_find(ctdb
, request
->rdata
.data
.pid
);
1325 if (cstate
== NULL
) {
1327 reply
.errmsg
= "No client for PID";
1329 reply
.status
= kill(request
->rdata
.data
.pid
, 0);
1330 reply
.errmsg
= NULL
;
1333 client_send_control(req
, header
, &reply
);
1336 static void control_ping(TALLOC_CTX
*mem_ctx
,
1337 struct tevent_req
*req
,
1338 struct ctdb_req_header
*header
,
1339 struct ctdb_req_control
*request
)
1341 struct client_state
*state
= tevent_req_data(
1342 req
, struct client_state
);
1343 struct ctdbd_context
*ctdb
= state
->ctdb
;
1344 struct ctdb_reply_control reply
;
1346 reply
.rdata
.opcode
= request
->opcode
;
1347 reply
.status
= ctdb
->num_clients
;
1348 reply
.errmsg
= NULL
;
1350 client_send_control(req
, header
, &reply
);
1353 static void control_getdbpath(TALLOC_CTX
*mem_ctx
,
1354 struct tevent_req
*req
,
1355 struct ctdb_req_header
*header
,
1356 struct ctdb_req_control
*request
)
1358 struct client_state
*state
= tevent_req_data(
1359 req
, struct client_state
);
1360 struct ctdbd_context
*ctdb
= state
->ctdb
;
1361 struct ctdb_reply_control reply
;
1362 struct database
*db
;
1364 reply
.rdata
.opcode
= request
->opcode
;
1366 db
= database_find(ctdb
->db_map
, request
->rdata
.data
.db_id
);
1368 reply
.status
= ENOENT
;
1369 reply
.errmsg
= "Database not found";
1372 if (db
->flags
& CTDB_DB_FLAGS_PERSISTENT
) {
1373 base
= "/var/lib/ctdb/persistent";
1375 base
= "/var/run/ctdb/DB_DIR";
1377 reply
.rdata
.data
.db_path
=
1378 talloc_asprintf(mem_ctx
, "%s/%s.%u",
1379 base
, db
->name
, header
->destnode
);
1380 if (reply
.rdata
.data
.db_path
== NULL
) {
1381 reply
.status
= ENOMEM
;
1382 reply
.errmsg
= "Memory error";
1385 reply
.errmsg
= NULL
;
1389 client_send_control(req
, header
, &reply
);
1392 static void control_getvnnmap(TALLOC_CTX
*mem_ctx
,
1393 struct tevent_req
*req
,
1394 struct ctdb_req_header
*header
,
1395 struct ctdb_req_control
*request
)
1397 struct client_state
*state
= tevent_req_data(
1398 req
, struct client_state
);
1399 struct ctdbd_context
*ctdb
= state
->ctdb
;
1400 struct ctdb_reply_control reply
;
1401 struct ctdb_vnn_map
*vnnmap
;
1403 reply
.rdata
.opcode
= request
->opcode
;
1405 vnnmap
= talloc_zero(mem_ctx
, struct ctdb_vnn_map
);
1406 if (vnnmap
== NULL
) {
1407 reply
.status
= ENOMEM
;
1408 reply
.errmsg
= "Memory error";
1410 vnnmap
->generation
= ctdb
->vnn_map
->generation
;
1411 vnnmap
->size
= ctdb
->vnn_map
->size
;
1412 vnnmap
->map
= ctdb
->vnn_map
->map
;
1414 reply
.rdata
.data
.vnnmap
= vnnmap
;
1416 reply
.errmsg
= NULL
;
1419 client_send_control(req
, header
, &reply
);
1422 static void control_get_debug(TALLOC_CTX
*mem_ctx
,
1423 struct tevent_req
*req
,
1424 struct ctdb_req_header
*header
,
1425 struct ctdb_req_control
*request
)
1427 struct client_state
*state
= tevent_req_data(
1428 req
, struct client_state
);
1429 struct ctdbd_context
*ctdb
= state
->ctdb
;
1430 struct ctdb_reply_control reply
;
1432 reply
.rdata
.opcode
= request
->opcode
;
1433 reply
.rdata
.data
.loglevel
= (uint32_t)ctdb
->log_level
;
1435 reply
.errmsg
= NULL
;
1437 client_send_control(req
, header
, &reply
);
1440 static void control_set_debug(TALLOC_CTX
*mem_ctx
,
1441 struct tevent_req
*req
,
1442 struct ctdb_req_header
*header
,
1443 struct ctdb_req_control
*request
)
1445 struct client_state
*state
= tevent_req_data(
1446 req
, struct client_state
);
1447 struct ctdbd_context
*ctdb
= state
->ctdb
;
1448 struct ctdb_reply_control reply
;
1450 ctdb
->log_level
= (int)request
->rdata
.data
.loglevel
;
1452 reply
.rdata
.opcode
= request
->opcode
;
1454 reply
.errmsg
= NULL
;
1456 client_send_control(req
, header
, &reply
);
1459 static void control_get_dbmap(TALLOC_CTX
*mem_ctx
,
1460 struct tevent_req
*req
,
1461 struct ctdb_req_header
*header
,
1462 struct ctdb_req_control
*request
)
1464 struct client_state
*state
= tevent_req_data(
1465 req
, struct client_state
);
1466 struct ctdbd_context
*ctdb
= state
->ctdb
;
1467 struct ctdb_reply_control reply
;
1468 struct ctdb_dbid_map
*dbmap
;
1471 reply
.rdata
.opcode
= request
->opcode
;
1473 dbmap
= talloc_zero(mem_ctx
, struct ctdb_dbid_map
);
1474 if (dbmap
== NULL
) {
1478 dbmap
->num
= ctdb
->db_map
->num_dbs
;
1479 dbmap
->dbs
= talloc_zero_array(dbmap
, struct ctdb_dbid
, dbmap
->num
);
1480 if (dbmap
->dbs
== NULL
) {
1484 for (i
= 0; i
< dbmap
->num
; i
++) {
1485 struct database
*db
= &ctdb
->db_map
->db
[i
];
1486 dbmap
->dbs
[i
] = (struct ctdb_dbid
) {
1492 reply
.rdata
.data
.dbmap
= dbmap
;
1494 reply
.errmsg
= NULL
;
1495 client_send_control(req
, header
, &reply
);
1500 reply
.errmsg
= "Memory error";
1501 client_send_control(req
, header
, &reply
);
1504 static void control_get_recmode(TALLOC_CTX
*mem_ctx
,
1505 struct tevent_req
*req
,
1506 struct ctdb_req_header
*header
,
1507 struct ctdb_req_control
*request
)
1509 struct client_state
*state
= tevent_req_data(
1510 req
, struct client_state
);
1511 struct ctdbd_context
*ctdb
= state
->ctdb
;
1512 struct ctdb_reply_control reply
;
1514 reply
.rdata
.opcode
= request
->opcode
;
1515 reply
.status
= ctdb
->vnn_map
->recmode
;
1516 reply
.errmsg
= NULL
;
1518 client_send_control(req
, header
, &reply
);
1521 struct set_recmode_state
{
1522 struct tevent_req
*req
;
1523 struct ctdbd_context
*ctdb
;
1524 struct ctdb_req_header header
;
1525 struct ctdb_reply_control reply
;
1528 static void set_recmode_callback(struct tevent_req
*subreq
)
1530 struct set_recmode_state
*substate
= tevent_req_callback_data(
1531 subreq
, struct set_recmode_state
);
1535 status
= recover_recv(subreq
, &ret
);
1536 TALLOC_FREE(subreq
);
1538 substate
->reply
.status
= ret
;
1539 substate
->reply
.errmsg
= "recovery failed";
1541 substate
->reply
.status
= 0;
1542 substate
->reply
.errmsg
= NULL
;
1545 client_send_control(substate
->req
, &substate
->header
, &substate
->reply
);
1546 talloc_free(substate
);
1549 static void control_set_recmode(TALLOC_CTX
*mem_ctx
,
1550 struct tevent_req
*req
,
1551 struct ctdb_req_header
*header
,
1552 struct ctdb_req_control
*request
)
1554 struct client_state
*state
= tevent_req_data(
1555 req
, struct client_state
);
1556 struct tevent_req
*subreq
;
1557 struct ctdbd_context
*ctdb
= state
->ctdb
;
1558 struct set_recmode_state
*substate
;
1559 struct ctdb_reply_control reply
;
1561 reply
.rdata
.opcode
= request
->opcode
;
1563 if (request
->rdata
.data
.recmode
== CTDB_RECOVERY_NORMAL
) {
1565 reply
.errmsg
= "Client cannot set recmode to NORMAL";
1569 substate
= talloc_zero(ctdb
, struct set_recmode_state
);
1570 if (substate
== NULL
) {
1572 reply
.errmsg
= "Memory error";
1576 substate
->req
= req
;
1577 substate
->ctdb
= ctdb
;
1578 substate
->header
= *header
;
1579 substate
->reply
.rdata
.opcode
= request
->opcode
;
1581 subreq
= recover_send(substate
, state
->ev
, state
->ctdb
);
1582 if (subreq
== NULL
) {
1583 talloc_free(substate
);
1586 tevent_req_set_callback(subreq
, set_recmode_callback
, substate
);
1588 ctdb
->vnn_map
->recmode
= CTDB_RECOVERY_ACTIVE
;
1592 client_send_control(req
, header
, &reply
);
1596 static void srvid_handler(uint64_t srvid
, TDB_DATA data
, void *private_data
)
1598 printf("Received a message for SRVID 0x%"PRIx64
"\n", srvid
);
1601 static void control_register_srvid(TALLOC_CTX
*mem_ctx
,
1602 struct tevent_req
*req
,
1603 struct ctdb_req_header
*header
,
1604 struct ctdb_req_control
*request
)
1606 struct client_state
*state
= tevent_req_data(
1607 req
, struct client_state
);
1608 struct ctdbd_context
*ctdb
= state
->ctdb
;
1609 struct ctdb_reply_control reply
;
1612 reply
.rdata
.opcode
= request
->opcode
;
1614 ret
= srvid_register(ctdb
->srv
, state
, request
->srvid
,
1615 srvid_handler
, state
);
1618 reply
.errmsg
= "Memory error";
1622 DEBUG(DEBUG_INFO
, ("Register srvid 0x%"PRIx64
"\n", request
->srvid
));
1625 reply
.errmsg
= NULL
;
1628 client_send_control(req
, header
, &reply
);
1631 static void control_deregister_srvid(TALLOC_CTX
*mem_ctx
,
1632 struct tevent_req
*req
,
1633 struct ctdb_req_header
*header
,
1634 struct ctdb_req_control
*request
)
1636 struct client_state
*state
= tevent_req_data(
1637 req
, struct client_state
);
1638 struct ctdbd_context
*ctdb
= state
->ctdb
;
1639 struct ctdb_reply_control reply
;
1642 reply
.rdata
.opcode
= request
->opcode
;
1644 ret
= srvid_deregister(ctdb
->srv
, request
->srvid
, state
);
1647 reply
.errmsg
= "srvid not registered";
1651 DEBUG(DEBUG_INFO
, ("Deregister srvid 0x%"PRIx64
"\n", request
->srvid
));
1654 reply
.errmsg
= NULL
;
1657 client_send_control(req
, header
, &reply
);
1660 static void control_get_dbname(TALLOC_CTX
*mem_ctx
,
1661 struct tevent_req
*req
,
1662 struct ctdb_req_header
*header
,
1663 struct ctdb_req_control
*request
)
1665 struct client_state
*state
= tevent_req_data(
1666 req
, struct client_state
);
1667 struct ctdbd_context
*ctdb
= state
->ctdb
;
1668 struct ctdb_reply_control reply
;
1669 struct database
*db
;
1671 reply
.rdata
.opcode
= request
->opcode
;
1673 db
= database_find(ctdb
->db_map
, request
->rdata
.data
.db_id
);
1675 reply
.status
= ENOENT
;
1676 reply
.errmsg
= "Database not found";
1678 reply
.rdata
.data
.db_name
= talloc_strdup(mem_ctx
, db
->name
);
1679 if (reply
.rdata
.data
.db_name
== NULL
) {
1680 reply
.status
= ENOMEM
;
1681 reply
.errmsg
= "Memory error";
1684 reply
.errmsg
= NULL
;
1688 client_send_control(req
, header
, &reply
);
1691 static void control_get_pid(TALLOC_CTX
*mem_ctx
,
1692 struct tevent_req
*req
,
1693 struct ctdb_req_header
*header
,
1694 struct ctdb_req_control
*request
)
1696 struct ctdb_reply_control reply
;
1698 reply
.rdata
.opcode
= request
->opcode
;
1699 reply
.status
= getpid();
1700 reply
.errmsg
= NULL
;
1702 client_send_control(req
, header
, &reply
);
1705 static void control_get_recmaster(TALLOC_CTX
*mem_ctx
,
1706 struct tevent_req
*req
,
1707 struct ctdb_req_header
*header
,
1708 struct ctdb_req_control
*request
)
1710 struct client_state
*state
= tevent_req_data(
1711 req
, struct client_state
);
1712 struct ctdbd_context
*ctdb
= state
->ctdb
;
1713 struct ctdb_reply_control reply
;
1715 reply
.rdata
.opcode
= request
->opcode
;
1716 reply
.status
= ctdb
->node_map
->recmaster
;
1717 reply
.errmsg
= NULL
;
1719 client_send_control(req
, header
, &reply
);
1722 static void control_get_pnn(TALLOC_CTX
*mem_ctx
,
1723 struct tevent_req
*req
,
1724 struct ctdb_req_header
*header
,
1725 struct ctdb_req_control
*request
)
1727 struct ctdb_reply_control reply
;
1729 reply
.rdata
.opcode
= request
->opcode
;
1730 reply
.status
= header
->destnode
;
1731 reply
.errmsg
= NULL
;
1733 client_send_control(req
, header
, &reply
);
1736 static void control_shutdown(TALLOC_CTX
*mem_ctx
,
1737 struct tevent_req
*req
,
1738 struct ctdb_req_header
*hdr
,
1739 struct ctdb_req_control
*request
)
1741 struct client_state
*state
= tevent_req_data(
1742 req
, struct client_state
);
1747 static void control_get_monmode(TALLOC_CTX
*mem_ctx
,
1748 struct tevent_req
*req
,
1749 struct ctdb_req_header
*header
,
1750 struct ctdb_req_control
*request
)
1752 struct client_state
*state
= tevent_req_data(
1753 req
, struct client_state
);
1754 struct ctdbd_context
*ctdb
= state
->ctdb
;
1755 struct ctdb_reply_control reply
;
1757 reply
.rdata
.opcode
= request
->opcode
;
1758 reply
.status
= ctdb
->monitoring_mode
;
1759 reply
.errmsg
= NULL
;
1761 client_send_control(req
, header
, &reply
);
1764 static void control_set_tunable(TALLOC_CTX
*mem_ctx
,
1765 struct tevent_req
*req
,
1766 struct ctdb_req_header
*header
,
1767 struct ctdb_req_control
*request
)
1769 struct client_state
*state
= tevent_req_data(
1770 req
, struct client_state
);
1771 struct ctdbd_context
*ctdb
= state
->ctdb
;
1772 struct ctdb_reply_control reply
;
1775 reply
.rdata
.opcode
= request
->opcode
;
1776 reply
.errmsg
= NULL
;
1778 ret
= ctdb_tunable_set_value(&ctdb
->tun_list
,
1779 request
->rdata
.data
.tunable
->name
,
1780 request
->rdata
.data
.tunable
->value
,
1784 } else if (obsolete
) {
1790 client_send_control(req
, header
, &reply
);
1793 static void control_get_tunable(TALLOC_CTX
*mem_ctx
,
1794 struct tevent_req
*req
,
1795 struct ctdb_req_header
*header
,
1796 struct ctdb_req_control
*request
)
1798 struct client_state
*state
= tevent_req_data(
1799 req
, struct client_state
);
1800 struct ctdbd_context
*ctdb
= state
->ctdb
;
1801 struct ctdb_reply_control reply
;
1805 reply
.rdata
.opcode
= request
->opcode
;
1806 reply
.errmsg
= NULL
;
1808 ret
= ctdb_tunable_get_value(&ctdb
->tun_list
,
1809 request
->rdata
.data
.tun_var
, &value
);
1813 reply
.rdata
.data
.tun_value
= value
;
1817 client_send_control(req
, header
, &reply
);
1820 static void control_list_tunables(TALLOC_CTX
*mem_ctx
,
1821 struct tevent_req
*req
,
1822 struct ctdb_req_header
*header
,
1823 struct ctdb_req_control
*request
)
1825 struct ctdb_reply_control reply
;
1826 struct ctdb_var_list
*var_list
;
1828 reply
.rdata
.opcode
= request
->opcode
;
1829 reply
.errmsg
= NULL
;
1831 var_list
= ctdb_tunable_names(mem_ctx
);
1832 if (var_list
== NULL
) {
1835 reply
.rdata
.data
.tun_var_list
= var_list
;
1839 client_send_control(req
, header
, &reply
);
1842 static void control_modify_flags(TALLOC_CTX
*mem_ctx
,
1843 struct tevent_req
*req
,
1844 struct ctdb_req_header
*header
,
1845 struct ctdb_req_control
*request
)
1847 struct client_state
*state
= tevent_req_data(
1848 req
, struct client_state
);
1849 struct ctdbd_context
*ctdb
= state
->ctdb
;
1850 struct ctdb_node_flag_change
*change
= request
->rdata
.data
.flag_change
;
1851 struct ctdb_reply_control reply
;
1854 reply
.rdata
.opcode
= request
->opcode
;
1856 if ((change
->old_flags
& ~NODE_FLAGS_PERMANENTLY_DISABLED
) ||
1857 (change
->new_flags
& ~NODE_FLAGS_PERMANENTLY_DISABLED
) != 0) {
1859 ("MODIFY_FLAGS control not for PERMANENTLY_DISABLED\n"));
1860 reply
.status
= EINVAL
;
1861 reply
.errmsg
= "Failed to MODIFY_FLAGS";
1862 client_send_control(req
, header
, &reply
);
1866 /* There's all sorts of broadcast weirdness here. Only change
1867 * the specified node, not the destination node of the
1869 node
= &ctdb
->node_map
->node
[change
->pnn
];
1872 change
->old_flags
& NODE_FLAGS_PERMANENTLY_DISABLED
) == 0 &&
1873 (change
->new_flags
& NODE_FLAGS_PERMANENTLY_DISABLED
) != 0) {
1874 DEBUG(DEBUG_INFO
,("Disabling node %d\n", header
->destnode
));
1875 node
->flags
|= NODE_FLAGS_PERMANENTLY_DISABLED
;
1880 change
->old_flags
& NODE_FLAGS_PERMANENTLY_DISABLED
) != 0 &&
1881 (change
->new_flags
& NODE_FLAGS_PERMANENTLY_DISABLED
) == 0) {
1882 DEBUG(DEBUG_INFO
,("Enabling node %d\n", header
->destnode
));
1883 node
->flags
&= ~NODE_FLAGS_PERMANENTLY_DISABLED
;
1887 DEBUG(DEBUG_INFO
, ("Flags unchanged for node %d\n", header
->destnode
));
1891 reply
.errmsg
= NULL
;
1892 client_send_control(req
, header
, &reply
);
1895 static void control_get_all_tunables(TALLOC_CTX
*mem_ctx
,
1896 struct tevent_req
*req
,
1897 struct ctdb_req_header
*header
,
1898 struct ctdb_req_control
*request
)
1900 struct client_state
*state
= tevent_req_data(
1901 req
, struct client_state
);
1902 struct ctdbd_context
*ctdb
= state
->ctdb
;
1903 struct ctdb_reply_control reply
;
1905 reply
.rdata
.opcode
= request
->opcode
;
1906 reply
.rdata
.data
.tun_list
= &ctdb
->tun_list
;
1908 reply
.errmsg
= NULL
;
1910 client_send_control(req
, header
, &reply
);
1913 static void control_uptime(TALLOC_CTX
*mem_ctx
,
1914 struct tevent_req
*req
,
1915 struct ctdb_req_header
*header
,
1916 struct ctdb_req_control
*request
)
1918 struct client_state
*state
= tevent_req_data(
1919 req
, struct client_state
);
1920 struct ctdbd_context
*ctdb
= state
->ctdb
;
1921 struct ctdb_reply_control reply
;
1922 struct ctdb_uptime
*uptime
;;
1924 reply
.rdata
.opcode
= request
->opcode
;
1926 uptime
= talloc_zero(mem_ctx
, struct ctdb_uptime
);
1927 if (uptime
== NULL
) {
1931 uptime
->current_time
= tevent_timeval_current();
1932 uptime
->ctdbd_start_time
= ctdb
->start_time
;
1933 uptime
->last_recovery_started
= ctdb
->recovery_start_time
;
1934 uptime
->last_recovery_finished
= ctdb
->recovery_end_time
;
1936 reply
.rdata
.data
.uptime
= uptime
;
1938 reply
.errmsg
= NULL
;
1939 client_send_control(req
, header
, &reply
);
1944 reply
.errmsg
= "Memory error";
1945 client_send_control(req
, header
, &reply
);
1948 static void control_enable_monitor(TALLOC_CTX
*mem_ctx
,
1949 struct tevent_req
*req
,
1950 struct ctdb_req_header
*header
,
1951 struct ctdb_req_control
*request
)
1953 struct client_state
*state
= tevent_req_data(
1954 req
, struct client_state
);
1955 struct ctdbd_context
*ctdb
= state
->ctdb
;
1956 struct ctdb_reply_control reply
;
1958 ctdb
->monitoring_mode
= CTDB_MONITORING_ENABLED
;
1960 reply
.rdata
.opcode
= request
->opcode
;
1962 reply
.errmsg
= NULL
;
1963 client_send_control(req
, header
, &reply
);
1966 static void control_disable_monitor(TALLOC_CTX
*mem_ctx
,
1967 struct tevent_req
*req
,
1968 struct ctdb_req_header
*header
,
1969 struct ctdb_req_control
*request
)
1971 struct client_state
*state
= tevent_req_data(
1972 req
, struct client_state
);
1973 struct ctdbd_context
*ctdb
= state
->ctdb
;
1974 struct ctdb_reply_control reply
;
1976 ctdb
->monitoring_mode
= CTDB_MONITORING_DISABLED
;
1978 reply
.rdata
.opcode
= request
->opcode
;
1980 reply
.errmsg
= NULL
;
1981 client_send_control(req
, header
, &reply
);
1984 static void control_reload_nodes_file(TALLOC_CTX
*mem_ctx
,
1985 struct tevent_req
*req
,
1986 struct ctdb_req_header
*header
,
1987 struct ctdb_req_control
*request
)
1989 struct client_state
*state
= tevent_req_data(
1990 req
, struct client_state
);
1991 struct ctdbd_context
*ctdb
= state
->ctdb
;
1992 struct ctdb_reply_control reply
;
1993 struct ctdb_node_map
*nodemap
;
1994 struct node_map
*node_map
= ctdb
->node_map
;
1997 reply
.rdata
.opcode
= request
->opcode
;
1999 nodemap
= read_nodes_file(mem_ctx
, header
->destnode
);
2000 if (nodemap
== NULL
) {
2004 for (i
=0; i
<nodemap
->num
; i
++) {
2007 if (i
< node_map
->num_nodes
&&
2008 ctdb_sock_addr_same(&nodemap
->node
[i
].addr
,
2009 &node_map
->node
[i
].addr
)) {
2013 if (nodemap
->node
[i
].flags
& NODE_FLAGS_DELETED
) {
2014 node
= &node_map
->node
[i
];
2016 node
->flags
|= NODE_FLAGS_DELETED
;
2017 parse_ip("0.0.0.0", NULL
, 0, &node
->addr
);
2022 if (i
< node_map
->num_nodes
&&
2023 node_map
->node
[i
].flags
& NODE_FLAGS_DELETED
) {
2024 node
= &node_map
->node
[i
];
2026 node
->flags
&= ~NODE_FLAGS_DELETED
;
2027 node
->addr
= nodemap
->node
[i
].addr
;
2032 node_map
->node
= talloc_realloc(node_map
, node_map
->node
,
2034 node_map
->num_nodes
+1);
2035 if (node_map
->node
== NULL
) {
2038 node
= &node_map
->node
[node_map
->num_nodes
];
2040 node
->addr
= nodemap
->node
[i
].addr
;
2041 node
->pnn
= nodemap
->node
[i
].pnn
;
2043 node
->capabilities
= CTDB_CAP_DEFAULT
;
2044 node
->recovery_disabled
= false;
2045 node
->recovery_substate
= NULL
;
2047 node_map
->num_nodes
+= 1;
2050 talloc_free(nodemap
);
2053 reply
.errmsg
= NULL
;
2054 client_send_control(req
, header
, &reply
);
2059 reply
.errmsg
= "Memory error";
2060 client_send_control(req
, header
, &reply
);
2063 static void control_get_capabilities(TALLOC_CTX
*mem_ctx
,
2064 struct tevent_req
*req
,
2065 struct ctdb_req_header
*header
,
2066 struct ctdb_req_control
*request
)
2068 struct client_state
*state
= tevent_req_data(
2069 req
, struct client_state
);
2070 struct ctdbd_context
*ctdb
= state
->ctdb
;
2071 struct ctdb_reply_control reply
;
2075 reply
.rdata
.opcode
= request
->opcode
;
2077 node
= &ctdb
->node_map
->node
[header
->destnode
];
2078 caps
= node
->capabilities
;
2080 if (node
->flags
& NODE_FLAGS_FAKE_TIMEOUT
) {
2081 /* Don't send reply */
2085 reply
.rdata
.data
.caps
= caps
;
2087 reply
.errmsg
= NULL
;
2089 client_send_control(req
, header
, &reply
);
2092 static void control_release_ip(TALLOC_CTX
*mem_ctx
,
2093 struct tevent_req
*req
,
2094 struct ctdb_req_header
*header
,
2095 struct ctdb_req_control
*request
)
2097 struct client_state
*state
= tevent_req_data(
2098 req
, struct client_state
);
2099 struct ctdbd_context
*ctdb
= state
->ctdb
;
2100 struct ctdb_public_ip
*ip
= request
->rdata
.data
.pubip
;
2101 struct ctdb_reply_control reply
;
2102 struct ctdb_public_ip_list
*ips
= NULL
;
2103 struct ctdb_public_ip
*t
= NULL
;
2106 reply
.rdata
.opcode
= request
->opcode
;
2108 if (ctdb
->known_ips
== NULL
) {
2109 D_INFO("RELEASE_IP %s - not a public IP\n",
2110 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
));
2114 ips
= &ctdb
->known_ips
[header
->destnode
];
2117 for (i
= 0; i
< ips
->num
; i
++) {
2118 if (ctdb_sock_addr_same_ip(&ips
->ip
[i
].addr
, &ip
->addr
)) {
2124 D_INFO("RELEASE_IP %s - not a public IP\n",
2125 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
));
2129 if (t
->pnn
!= header
->destnode
) {
2130 if (header
->destnode
== ip
->pnn
) {
2131 D_ERR("error: RELEASE_IP %s - to TAKE_IP node %d\n",
2132 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
),
2135 reply
.errmsg
= "RELEASE_IP to TAKE_IP node";
2136 client_send_control(req
, header
, &reply
);
2140 D_INFO("RELEASE_IP %s - to node %d - redundant\n",
2141 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
),
2145 D_NOTICE("RELEASE_IP %s - to node %d\n",
2146 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
),
2153 reply
.errmsg
= NULL
;
2154 client_send_control(req
, header
, &reply
);
2157 static void control_takeover_ip(TALLOC_CTX
*mem_ctx
,
2158 struct tevent_req
*req
,
2159 struct ctdb_req_header
*header
,
2160 struct ctdb_req_control
*request
)
2162 struct client_state
*state
= tevent_req_data(
2163 req
, struct client_state
);
2164 struct ctdbd_context
*ctdb
= state
->ctdb
;
2165 struct ctdb_public_ip
*ip
= request
->rdata
.data
.pubip
;
2166 struct ctdb_reply_control reply
;
2167 struct ctdb_public_ip_list
*ips
= NULL
;
2168 struct ctdb_public_ip
*t
= NULL
;
2171 reply
.rdata
.opcode
= request
->opcode
;
2173 if (ctdb
->known_ips
== NULL
) {
2174 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2175 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
));
2179 ips
= &ctdb
->known_ips
[header
->destnode
];
2182 for (i
= 0; i
< ips
->num
; i
++) {
2183 if (ctdb_sock_addr_same_ip(&ips
->ip
[i
].addr
, &ip
->addr
)) {
2189 D_INFO("TAKEOVER_IP %s - not a public IP\n",
2190 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
));
2194 if (t
->pnn
== header
->destnode
) {
2195 D_INFO("TAKEOVER_IP %s - redundant\n",
2196 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
));
2198 D_NOTICE("TAKEOVER_IP %s\n",
2199 ctdb_sock_addr_to_string(mem_ctx
, &ip
->addr
));
2205 reply
.errmsg
= NULL
;
2206 client_send_control(req
, header
, &reply
);
2209 static void control_get_public_ips(TALLOC_CTX
*mem_ctx
,
2210 struct tevent_req
*req
,
2211 struct ctdb_req_header
*header
,
2212 struct ctdb_req_control
*request
)
2214 struct client_state
*state
= tevent_req_data(
2215 req
, struct client_state
);
2216 struct ctdbd_context
*ctdb
= state
->ctdb
;
2217 struct ctdb_reply_control reply
;
2218 struct ctdb_public_ip_list
*ips
= NULL
;
2220 reply
.rdata
.opcode
= request
->opcode
;
2222 if (ctdb
->known_ips
== NULL
) {
2223 /* No IPs defined so create a dummy empty struct and ship it */
2224 ips
= talloc_zero(mem_ctx
, struct ctdb_public_ip_list
);;
2226 reply
.status
= ENOMEM
;
2227 reply
.errmsg
= "Memory error";
2233 ips
= &ctdb
->known_ips
[header
->destnode
];
2235 if (request
->flags
& CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE
) {
2236 /* If runstate is not RUNNING or a node is then return
2237 * no available IPs. Don't worry about interface
2238 * states here - we're not faking down to that level.
2240 if (ctdb
->runstate
!= CTDB_RUNSTATE_RUNNING
) {
2241 /* No available IPs: return dummy empty struct */
2242 ips
= talloc_zero(mem_ctx
, struct ctdb_public_ip_list
);;
2244 reply
.status
= ENOMEM
;
2245 reply
.errmsg
= "Memory error";
2252 reply
.rdata
.data
.pubip_list
= ips
;
2254 reply
.errmsg
= NULL
;
2257 client_send_control(req
, header
, &reply
);
2260 static void control_get_nodemap(TALLOC_CTX
*mem_ctx
,
2261 struct tevent_req
*req
,
2262 struct ctdb_req_header
*header
,
2263 struct ctdb_req_control
*request
)
2265 struct client_state
*state
= tevent_req_data(
2266 req
, struct client_state
);
2267 struct ctdbd_context
*ctdb
= state
->ctdb
;
2268 struct ctdb_reply_control reply
;
2269 struct ctdb_node_map
*nodemap
;
2273 reply
.rdata
.opcode
= request
->opcode
;
2275 nodemap
= talloc_zero(mem_ctx
, struct ctdb_node_map
);
2276 if (nodemap
== NULL
) {
2280 nodemap
->num
= ctdb
->node_map
->num_nodes
;
2281 nodemap
->node
= talloc_array(nodemap
, struct ctdb_node_and_flags
,
2283 if (nodemap
->node
== NULL
) {
2287 for (i
=0; i
<nodemap
->num
; i
++) {
2288 node
= &ctdb
->node_map
->node
[i
];
2289 nodemap
->node
[i
] = (struct ctdb_node_and_flags
) {
2291 .flags
= node
->flags
,
2296 reply
.rdata
.data
.nodemap
= nodemap
;
2298 reply
.errmsg
= NULL
;
2299 client_send_control(req
, header
, &reply
);
2304 reply
.errmsg
= "Memory error";
2305 client_send_control(req
, header
, &reply
);
2308 static void control_get_reclock_file(TALLOC_CTX
*mem_ctx
,
2309 struct tevent_req
*req
,
2310 struct ctdb_req_header
*header
,
2311 struct ctdb_req_control
*request
)
2313 struct client_state
*state
= tevent_req_data(
2314 req
, struct client_state
);
2315 struct ctdbd_context
*ctdb
= state
->ctdb
;
2316 struct ctdb_reply_control reply
;
2318 reply
.rdata
.opcode
= request
->opcode
;
2320 if (ctdb
->reclock
!= NULL
) {
2321 reply
.rdata
.data
.reclock_file
=
2322 talloc_strdup(mem_ctx
, ctdb
->reclock
);
2323 if (reply
.rdata
.data
.reclock_file
== NULL
) {
2324 reply
.status
= ENOMEM
;
2325 reply
.errmsg
= "Memory error";
2329 reply
.rdata
.data
.reclock_file
= NULL
;
2333 reply
.errmsg
= NULL
;
2336 client_send_control(req
, header
, &reply
);
2339 static void control_stop_node(TALLOC_CTX
*mem_ctx
,
2340 struct tevent_req
*req
,
2341 struct ctdb_req_header
*header
,
2342 struct ctdb_req_control
*request
)
2344 struct client_state
*state
= tevent_req_data(
2345 req
, struct client_state
);
2346 struct ctdbd_context
*ctdb
= state
->ctdb
;
2347 struct ctdb_reply_control reply
;
2349 reply
.rdata
.opcode
= request
->opcode
;
2351 DEBUG(DEBUG_INFO
, ("Stopping node\n"));
2352 ctdb
->monitoring_mode
= CTDB_MONITORING_DISABLED
;
2353 ctdb
->node_map
->node
[header
->destnode
].flags
|= NODE_FLAGS_STOPPED
;
2356 reply
.errmsg
= NULL
;
2358 client_send_control(req
, header
, &reply
);
2362 static void control_continue_node(TALLOC_CTX
*mem_ctx
,
2363 struct tevent_req
*req
,
2364 struct ctdb_req_header
*header
,
2365 struct ctdb_req_control
*request
)
2367 struct client_state
*state
= tevent_req_data(
2368 req
, struct client_state
);
2369 struct ctdbd_context
*ctdb
= state
->ctdb
;
2370 struct ctdb_reply_control reply
;
2372 reply
.rdata
.opcode
= request
->opcode
;
2374 DEBUG(DEBUG_INFO
, ("Continue node\n"));
2375 ctdb
->node_map
->node
[header
->destnode
].flags
&= ~NODE_FLAGS_STOPPED
;
2378 reply
.errmsg
= NULL
;
2380 client_send_control(req
, header
, &reply
);
2384 static void set_ban_state_callback(struct tevent_req
*subreq
)
2386 struct node
*node
= tevent_req_callback_data(
2387 subreq
, struct node
);
2390 status
= tevent_wakeup_recv(subreq
);
2391 TALLOC_FREE(subreq
);
2393 DEBUG(DEBUG_INFO
, ("tevent_wakeup_recv failed\n"));
2396 node
->flags
&= ~NODE_FLAGS_BANNED
;
2399 static void control_set_ban_state(TALLOC_CTX
*mem_ctx
,
2400 struct tevent_req
*req
,
2401 struct ctdb_req_header
*header
,
2402 struct ctdb_req_control
*request
)
2404 struct client_state
*state
= tevent_req_data(
2405 req
, struct client_state
);
2406 struct tevent_req
*subreq
;
2407 struct ctdbd_context
*ctdb
= state
->ctdb
;
2408 struct ctdb_ban_state
*ban
= request
->rdata
.data
.ban_state
;
2409 struct ctdb_reply_control reply
;
2412 reply
.rdata
.opcode
= request
->opcode
;
2414 if (ban
->pnn
!= header
->destnode
) {
2416 ("SET_BAN_STATE control for PNN %d rejected\n",
2418 reply
.status
= EINVAL
;
2422 node
= &ctdb
->node_map
->node
[header
->destnode
];
2424 if (ban
->time
== 0) {
2425 DEBUG(DEBUG_INFO
,("Unbanning this node\n"));
2426 node
->flags
&= ~NODE_FLAGS_BANNED
;
2430 subreq
= tevent_wakeup_send(ctdb
->node_map
, state
->ev
,
2431 tevent_timeval_current_ofs(
2433 if (subreq
== NULL
) {
2434 reply
.status
= ENOMEM
;
2437 tevent_req_set_callback(subreq
, set_ban_state_callback
, node
);
2439 DEBUG(DEBUG_INFO
, ("Banning this node for %d seconds\n", ban
->time
));
2440 node
->flags
|= NODE_FLAGS_BANNED
;
2441 ctdb
->vnn_map
->generation
= INVALID_GENERATION
;
2445 reply
.errmsg
= NULL
;
2447 client_send_control(req
, header
, &reply
);
2451 reply
.errmsg
= "Failed to ban node";
2454 static void control_get_db_seqnum(TALLOC_CTX
*mem_ctx
,
2455 struct tevent_req
*req
,
2456 struct ctdb_req_header
*header
,
2457 struct ctdb_req_control
*request
)
2459 struct client_state
*state
= tevent_req_data(
2460 req
, struct client_state
);
2461 struct ctdbd_context
*ctdb
= state
->ctdb
;
2462 struct ctdb_reply_control reply
;
2463 struct database
*db
;
2465 reply
.rdata
.opcode
= request
->opcode
;
2467 db
= database_find(ctdb
->db_map
, request
->rdata
.data
.db_id
);
2469 reply
.status
= ENOENT
;
2470 reply
.errmsg
= "Database not found";
2472 reply
.rdata
.data
.seqnum
= db
->seq_num
;
2474 reply
.errmsg
= NULL
;
2477 client_send_control(req
, header
, &reply
);
2480 static void control_db_get_health(TALLOC_CTX
*mem_ctx
,
2481 struct tevent_req
*req
,
2482 struct ctdb_req_header
*header
,
2483 struct ctdb_req_control
*request
)
2485 struct client_state
*state
= tevent_req_data(
2486 req
, struct client_state
);
2487 struct ctdbd_context
*ctdb
= state
->ctdb
;
2488 struct ctdb_reply_control reply
;
2489 struct database
*db
;
2491 reply
.rdata
.opcode
= request
->opcode
;
2493 db
= database_find(ctdb
->db_map
, request
->rdata
.data
.db_id
);
2495 reply
.status
= ENOENT
;
2496 reply
.errmsg
= "Database not found";
2498 reply
.rdata
.data
.reason
= NULL
;
2500 reply
.errmsg
= NULL
;
2503 client_send_control(req
, header
, &reply
);
2506 static struct ctdb_iface_list
*get_ctdb_iface_list(TALLOC_CTX
*mem_ctx
,
2507 struct ctdbd_context
*ctdb
)
2509 struct ctdb_iface_list
*iface_list
;
2510 struct interface
*iface
;
2513 iface_list
= talloc_zero(mem_ctx
, struct ctdb_iface_list
);
2514 if (iface_list
== NULL
) {
2518 iface_list
->num
= ctdb
->iface_map
->num
;
2519 iface_list
->iface
= talloc_array(iface_list
, struct ctdb_iface
,
2521 if (iface_list
->iface
== NULL
) {
2522 TALLOC_FREE(iface_list
);
2526 for (i
=0; i
<iface_list
->num
; i
++) {
2527 iface
= &ctdb
->iface_map
->iface
[i
];
2528 iface_list
->iface
[i
] = (struct ctdb_iface
) {
2529 .link_state
= iface
->link_up
,
2530 .references
= iface
->references
,
2532 strlcpy(iface_list
->iface
[i
].name
, iface
->name
,
2533 sizeof(iface_list
->iface
[i
].name
));
2540 static void control_get_public_ip_info(TALLOC_CTX
*mem_ctx
,
2541 struct tevent_req
*req
,
2542 struct ctdb_req_header
*header
,
2543 struct ctdb_req_control
*request
)
2545 struct client_state
*state
= tevent_req_data(
2546 req
, struct client_state
);
2547 struct ctdbd_context
*ctdb
= state
->ctdb
;
2548 struct ctdb_reply_control reply
;
2549 ctdb_sock_addr
*addr
= request
->rdata
.data
.addr
;
2550 struct ctdb_public_ip_list
*known
= NULL
;
2551 struct ctdb_public_ip_info
*info
= NULL
;
2554 reply
.rdata
.opcode
= request
->opcode
;
2556 info
= talloc_zero(mem_ctx
, struct ctdb_public_ip_info
);
2558 reply
.status
= ENOMEM
;
2559 reply
.errmsg
= "Memory error";
2563 reply
.rdata
.data
.ipinfo
= info
;
2565 if (ctdb
->known_ips
!= NULL
) {
2566 known
= &ctdb
->known_ips
[header
->destnode
];
2568 /* No IPs defined so create a dummy empty struct and
2569 * fall through. The given IP won't be matched
2572 known
= talloc_zero(mem_ctx
, struct ctdb_public_ip_list
);;
2573 if (known
== NULL
) {
2574 reply
.status
= ENOMEM
;
2575 reply
.errmsg
= "Memory error";
2580 for (i
= 0; i
< known
->num
; i
++) {
2581 if (ctdb_sock_addr_same_ip(&known
->ip
[i
].addr
,
2587 if (i
== known
->num
) {
2588 D_ERR("GET_PUBLIC_IP_INFO: not known public IP %s\n",
2589 ctdb_sock_addr_to_string(mem_ctx
, addr
));
2591 reply
.errmsg
= "Unknown address";
2595 info
->ip
= known
->ip
[i
];
2597 /* The fake PUBLICIPS stanza and resulting known_ips data
2598 * don't know anything about interfaces, so completely fake
2601 info
->active_idx
= 0;
2603 info
->ifaces
= get_ctdb_iface_list(mem_ctx
, ctdb
);
2604 if (info
->ifaces
== NULL
) {
2605 reply
.status
= ENOMEM
;
2606 reply
.errmsg
= "Memory error";
2611 reply
.errmsg
= NULL
;
2614 client_send_control(req
, header
, &reply
);
2617 static void control_get_ifaces(TALLOC_CTX
*mem_ctx
,
2618 struct tevent_req
*req
,
2619 struct ctdb_req_header
*header
,
2620 struct ctdb_req_control
*request
)
2622 struct client_state
*state
= tevent_req_data(
2623 req
, struct client_state
);
2624 struct ctdbd_context
*ctdb
= state
->ctdb
;
2625 struct ctdb_reply_control reply
;
2626 struct ctdb_iface_list
*iface_list
;
2628 reply
.rdata
.opcode
= request
->opcode
;
2630 iface_list
= get_ctdb_iface_list(mem_ctx
, ctdb
);
2631 if (iface_list
== NULL
) {
2635 reply
.rdata
.data
.iface_list
= iface_list
;
2637 reply
.errmsg
= NULL
;
2638 client_send_control(req
, header
, &reply
);
2643 reply
.errmsg
= "Memory error";
2644 client_send_control(req
, header
, &reply
);
2647 static void control_set_iface_link_state(TALLOC_CTX
*mem_ctx
,
2648 struct tevent_req
*req
,
2649 struct ctdb_req_header
*header
,
2650 struct ctdb_req_control
*request
)
2652 struct client_state
*state
= tevent_req_data(
2653 req
, struct client_state
);
2654 struct ctdbd_context
*ctdb
= state
->ctdb
;
2655 struct ctdb_reply_control reply
;
2656 struct ctdb_iface
*in_iface
;
2657 struct interface
*iface
= NULL
;
2658 bool link_up
= false;
2661 reply
.rdata
.opcode
= request
->opcode
;
2663 in_iface
= request
->rdata
.data
.iface
;
2665 if (in_iface
->name
[CTDB_IFACE_SIZE
] != '\0') {
2666 reply
.errmsg
= "interface name not terminated";
2670 switch (in_iface
->link_state
) {
2680 reply
.errmsg
= "invalid link state";
2684 if (in_iface
->references
!= 0) {
2685 reply
.errmsg
= "references should be 0";
2689 for (i
=0; i
<ctdb
->iface_map
->num
; i
++) {
2690 if (strcmp(ctdb
->iface_map
->iface
[i
].name
,
2691 in_iface
->name
) == 0) {
2692 iface
= &ctdb
->iface_map
->iface
[i
];
2697 if (iface
== NULL
) {
2698 reply
.errmsg
= "interface not found";
2702 iface
->link_up
= link_up
;
2705 reply
.errmsg
= NULL
;
2706 client_send_control(req
, header
, &reply
);
2711 client_send_control(req
, header
, &reply
);
2714 static void control_set_db_readonly(TALLOC_CTX
*mem_ctx
,
2715 struct tevent_req
*req
,
2716 struct ctdb_req_header
*header
,
2717 struct ctdb_req_control
*request
)
2719 struct client_state
*state
= tevent_req_data(
2720 req
, struct client_state
);
2721 struct ctdbd_context
*ctdb
= state
->ctdb
;
2722 struct ctdb_reply_control reply
;
2723 struct database
*db
;
2725 reply
.rdata
.opcode
= request
->opcode
;
2727 db
= database_find(ctdb
->db_map
, request
->rdata
.data
.db_id
);
2729 reply
.status
= ENOENT
;
2730 reply
.errmsg
= "Database not found";
2734 if (db
->flags
& CTDB_DB_FLAGS_PERSISTENT
) {
2735 reply
.status
= EINVAL
;
2736 reply
.errmsg
= "Can not set READONLY on persistent db";
2740 db
->flags
|= CTDB_DB_FLAGS_READONLY
;
2742 reply
.errmsg
= NULL
;
2745 client_send_control(req
, header
, &reply
);
2748 static void control_set_db_sticky(TALLOC_CTX
*mem_ctx
,
2749 struct tevent_req
*req
,
2750 struct ctdb_req_header
*header
,
2751 struct ctdb_req_control
*request
)
2753 struct client_state
*state
= tevent_req_data(
2754 req
, struct client_state
);
2755 struct ctdbd_context
*ctdb
= state
->ctdb
;
2756 struct ctdb_reply_control reply
;
2757 struct database
*db
;
2759 reply
.rdata
.opcode
= request
->opcode
;
2761 db
= database_find(ctdb
->db_map
, request
->rdata
.data
.db_id
);
2763 reply
.status
= ENOENT
;
2764 reply
.errmsg
= "Database not found";
2768 if (db
->flags
& CTDB_DB_FLAGS_PERSISTENT
) {
2769 reply
.status
= EINVAL
;
2770 reply
.errmsg
= "Can not set STICKY on persistent db";
2774 db
->flags
|= CTDB_DB_FLAGS_STICKY
;
2776 reply
.errmsg
= NULL
;
2779 client_send_control(req
, header
, &reply
);
2782 static void control_ipreallocated(TALLOC_CTX
*mem_ctx
,
2783 struct tevent_req
*req
,
2784 struct ctdb_req_header
*header
,
2785 struct ctdb_req_control
*request
)
2787 struct ctdb_reply_control reply
;
2789 /* Always succeed */
2790 reply
.rdata
.opcode
= request
->opcode
;
2792 reply
.errmsg
= NULL
;
2794 client_send_control(req
, header
, &reply
);
2797 static void control_get_runstate(TALLOC_CTX
*mem_ctx
,
2798 struct tevent_req
*req
,
2799 struct ctdb_req_header
*header
,
2800 struct ctdb_req_control
*request
)
2802 struct client_state
*state
= tevent_req_data(
2803 req
, struct client_state
);
2804 struct ctdbd_context
*ctdb
= state
->ctdb
;
2805 struct ctdb_reply_control reply
;
2807 reply
.rdata
.opcode
= request
->opcode
;
2808 reply
.rdata
.data
.runstate
= ctdb
->runstate
;
2810 reply
.errmsg
= NULL
;
2812 client_send_control(req
, header
, &reply
);
2815 static void control_get_nodes_file(TALLOC_CTX
*mem_ctx
,
2816 struct tevent_req
*req
,
2817 struct ctdb_req_header
*header
,
2818 struct ctdb_req_control
*request
)
2820 struct ctdb_reply_control reply
;
2821 struct ctdb_node_map
*nodemap
;
2823 reply
.rdata
.opcode
= request
->opcode
;
2825 nodemap
= read_nodes_file(mem_ctx
, header
->destnode
);
2826 if (nodemap
== NULL
) {
2830 reply
.rdata
.data
.nodemap
= nodemap
;
2832 reply
.errmsg
= NULL
;
2833 client_send_control(req
, header
, &reply
);
2838 reply
.errmsg
= "Failed to read nodes file";
2839 client_send_control(req
, header
, &reply
);
2842 static void control_check_pid_srvid(TALLOC_CTX
*mem_ctx
,
2843 struct tevent_req
*req
,
2844 struct ctdb_req_header
*header
,
2845 struct ctdb_req_control
*request
)
2847 struct client_state
*state
= tevent_req_data(
2848 req
, struct client_state
);
2849 struct ctdbd_context
*ctdb
= state
->ctdb
;
2850 struct client_state
*cstate
;
2851 struct ctdb_reply_control reply
;
2854 reply
.rdata
.opcode
= request
->opcode
;
2856 cstate
= client_find(ctdb
, request
->rdata
.data
.pid_srvid
->pid
);
2857 if (cstate
== NULL
) {
2859 reply
.errmsg
= "No client for PID";
2861 ret
= srvid_exists(ctdb
->srv
,
2862 request
->rdata
.data
.pid_srvid
->srvid
,
2866 reply
.errmsg
= "No client for PID and SRVID";
2868 ret
= kill(cstate
->pid
, 0);
2871 reply
.errmsg
= strerror(errno
);
2874 reply
.errmsg
= NULL
;
2879 client_send_control(req
, header
, &reply
);
2882 static bool fake_control_failure(TALLOC_CTX
*mem_ctx
,
2883 struct tevent_req
*req
,
2884 struct ctdb_req_header
*header
,
2885 struct ctdb_req_control
*request
)
2887 struct client_state
*state
= tevent_req_data(
2888 req
, struct client_state
);
2889 struct ctdbd_context
*ctdb
= state
->ctdb
;
2890 struct ctdb_reply_control reply
;
2891 struct fake_control_failure
*f
= NULL
;
2893 D_DEBUG("Checking fake control failure for control %u on node %u\n",
2894 request
->opcode
, header
->destnode
);
2895 for (f
= ctdb
->control_failures
; f
!= NULL
; f
= f
->next
) {
2896 if (f
->opcode
== request
->opcode
&&
2897 (f
->pnn
== header
->destnode
||
2898 f
->pnn
== CTDB_UNKNOWN_PNN
)) {
2900 reply
.rdata
.opcode
= request
->opcode
;
2901 if (strcmp(f
->error
, "TIMEOUT") == 0) {
2902 /* Causes no reply */
2903 D_ERR("Control %u fake timeout on node %u\n",
2904 request
->opcode
, header
->destnode
);
2906 } else if (strcmp(f
->error
, "ERROR") == 0) {
2907 D_ERR("Control %u fake error on node %u\n",
2908 request
->opcode
, header
->destnode
);
2910 reply
.errmsg
= f
->comment
;
2911 client_send_control(req
, header
, &reply
);
2920 static void control_error(TALLOC_CTX
*mem_ctx
,
2921 struct tevent_req
*req
,
2922 struct ctdb_req_header
*header
,
2923 struct ctdb_req_control
*request
)
2925 struct ctdb_reply_control reply
;
2927 reply
.rdata
.opcode
= request
->opcode
;
2929 reply
.errmsg
= "Not implemented";
2931 client_send_control(req
, header
, &reply
);
2935 * Handling protocol - messages
2938 struct disable_recoveries_state
{
2942 static void disable_recoveries_callback(struct tevent_req
*subreq
)
2944 struct disable_recoveries_state
*substate
= tevent_req_callback_data(
2945 subreq
, struct disable_recoveries_state
);
2948 status
= tevent_wakeup_recv(subreq
);
2949 TALLOC_FREE(subreq
);
2951 DEBUG(DEBUG_INFO
, ("tevent_wakeup_recv failed\n"));
2954 substate
->node
->recovery_disabled
= false;
2955 TALLOC_FREE(substate
->node
->recovery_substate
);
2958 static void message_disable_recoveries(TALLOC_CTX
*mem_ctx
,
2959 struct tevent_req
*req
,
2960 struct ctdb_req_header
*header
,
2961 struct ctdb_req_message
*request
)
2963 struct client_state
*state
= tevent_req_data(
2964 req
, struct client_state
);
2965 struct tevent_req
*subreq
;
2966 struct ctdbd_context
*ctdb
= state
->ctdb
;
2967 struct disable_recoveries_state
*substate
;
2968 struct ctdb_disable_message
*disable
= request
->data
.disable
;
2969 struct ctdb_req_message_data reply
;
2974 node
= &ctdb
->node_map
->node
[header
->destnode
];
2976 if (disable
->timeout
== 0) {
2977 TALLOC_FREE(node
->recovery_substate
);
2978 node
->recovery_disabled
= false;
2979 DEBUG(DEBUG_INFO
, ("Enabled recoveries on node %u\n",
2984 substate
= talloc_zero(ctdb
->node_map
,
2985 struct disable_recoveries_state
);
2986 if (substate
== NULL
) {
2990 substate
->node
= node
;
2992 subreq
= tevent_wakeup_send(substate
, state
->ev
,
2993 tevent_timeval_current_ofs(
2994 disable
->timeout
, 0));
2995 if (subreq
== NULL
) {
2996 talloc_free(substate
);
2999 tevent_req_set_callback(subreq
, disable_recoveries_callback
, substate
);
3001 DEBUG(DEBUG_INFO
, ("Disabled recoveries for %d seconds on node %u\n",
3002 disable
->timeout
, header
->destnode
));
3003 node
->recovery_substate
= substate
;
3004 node
->recovery_disabled
= true;
3007 ret
= header
->destnode
;
3010 reply
.srvid
= disable
->srvid
;
3011 data
.dptr
= (uint8_t *)&ret
;
3012 data
.dsize
= sizeof(int);
3015 client_send_message(req
, header
, &reply
);
3018 static void message_takeover_run(TALLOC_CTX
*mem_ctx
,
3019 struct tevent_req
*req
,
3020 struct ctdb_req_header
*header
,
3021 struct ctdb_req_message
*request
)
3023 struct client_state
*state
= tevent_req_data(
3024 req
, struct client_state
);
3025 struct ctdbd_context
*ctdb
= state
->ctdb
;
3026 struct ctdb_srvid_message
*srvid
= request
->data
.msg
;
3027 struct ctdb_req_message_data reply
;
3031 if (header
->destnode
!= ctdb
->node_map
->recmaster
) {
3032 /* No reply! Only recmaster replies... */
3036 DEBUG(DEBUG_INFO
, ("IP takover run on node %u\n",
3038 ret
= header
->destnode
;
3040 reply
.srvid
= srvid
->srvid
;
3041 data
.dptr
= (uint8_t *)&ret
;
3042 data
.dsize
= sizeof(int);
3045 client_send_message(req
, header
, &reply
);
3049 * Handle a single client
3052 static void client_read_handler(uint8_t *buf
, size_t buflen
,
3053 void *private_data
);
3054 static void client_dead_handler(void *private_data
);
3055 static void client_process_packet(struct tevent_req
*req
,
3056 uint8_t *buf
, size_t buflen
);
3057 static void client_process_message(struct tevent_req
*req
,
3058 uint8_t *buf
, size_t buflen
);
3059 static void client_process_control(struct tevent_req
*req
,
3060 uint8_t *buf
, size_t buflen
);
3061 static void client_reply_done(struct tevent_req
*subreq
);
3063 static struct tevent_req
*client_send(TALLOC_CTX
*mem_ctx
,
3064 struct tevent_context
*ev
,
3065 int fd
, struct ctdbd_context
*ctdb
,
3068 struct tevent_req
*req
;
3069 struct client_state
*state
;
3071 socklen_t crl
= sizeof(struct ucred
);
3074 req
= tevent_req_create(mem_ctx
, &state
, struct client_state
);
3084 ret
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &cr
, &crl
);
3086 tevent_req_error(req
, ret
);
3087 return tevent_req_post(req
, ev
);
3089 state
->pid
= cr
.pid
;
3091 ret
= comm_setup(state
, ev
, fd
, client_read_handler
, req
,
3092 client_dead_handler
, req
, &state
->comm
);
3094 tevent_req_error(req
, ret
);
3095 return tevent_req_post(req
, ev
);
3098 ret
= client_add(ctdb
, state
->pid
, state
);
3100 tevent_req_error(req
, ret
);
3101 return tevent_req_post(req
, ev
);
3104 DEBUG(DEBUG_INFO
, ("New client fd=%d\n", fd
));
3109 static void client_read_handler(uint8_t *buf
, size_t buflen
,
3112 struct tevent_req
*req
= talloc_get_type_abort(
3113 private_data
, struct tevent_req
);
3114 struct client_state
*state
= tevent_req_data(
3115 req
, struct client_state
);
3116 struct ctdbd_context
*ctdb
= state
->ctdb
;
3117 struct ctdb_req_header header
;
3120 ret
= ctdb_req_header_pull(buf
, buflen
, &header
);
3125 if (buflen
!= header
.length
) {
3129 ret
= ctdb_req_header_verify(&header
, 0);
3134 header_fix_pnn(&header
, ctdb
);
3136 if (header
.destnode
== CTDB_BROADCAST_ALL
) {
3137 for (i
=0; i
<ctdb
->node_map
->num_nodes
; i
++) {
3138 header
.destnode
= i
;
3140 ctdb_req_header_push(&header
, buf
);
3141 client_process_packet(req
, buf
, buflen
);
3146 if (header
.destnode
== CTDB_BROADCAST_CONNECTED
) {
3147 for (i
=0; i
<ctdb
->node_map
->num_nodes
; i
++) {
3148 if (ctdb
->node_map
->node
[i
].flags
&
3149 NODE_FLAGS_DISCONNECTED
) {
3153 header
.destnode
= i
;
3155 ctdb_req_header_push(&header
, buf
);
3156 client_process_packet(req
, buf
, buflen
);
3161 if (header
.destnode
> ctdb
->node_map
->num_nodes
) {
3162 fprintf(stderr
, "Invalid destination pnn 0x%x\n",
3168 if (ctdb
->node_map
->node
[header
.destnode
].flags
& NODE_FLAGS_DISCONNECTED
) {
3169 fprintf(stderr
, "Packet for disconnected node pnn %u\n",
3174 ctdb_req_header_push(&header
, buf
);
3175 client_process_packet(req
, buf
, buflen
);
3178 static void client_dead_handler(void *private_data
)
3180 struct tevent_req
*req
= talloc_get_type_abort(
3181 private_data
, struct tevent_req
);
3183 tevent_req_done(req
);
3186 static void client_process_packet(struct tevent_req
*req
,
3187 uint8_t *buf
, size_t buflen
)
3189 struct ctdb_req_header header
;
3192 ret
= ctdb_req_header_pull(buf
, buflen
, &header
);
3197 switch (header
.operation
) {
3198 case CTDB_REQ_MESSAGE
:
3199 client_process_message(req
, buf
, buflen
);
3202 case CTDB_REQ_CONTROL
:
3203 client_process_control(req
, buf
, buflen
);
3211 static void client_process_message(struct tevent_req
*req
,
3212 uint8_t *buf
, size_t buflen
)
3214 struct client_state
*state
= tevent_req_data(
3215 req
, struct client_state
);
3216 struct ctdbd_context
*ctdb
= state
->ctdb
;
3217 TALLOC_CTX
*mem_ctx
;
3218 struct ctdb_req_header header
;
3219 struct ctdb_req_message request
;
3223 mem_ctx
= talloc_new(state
);
3224 if (tevent_req_nomem(mem_ctx
, req
)) {
3228 ret
= ctdb_req_message_pull(buf
, buflen
, &header
, mem_ctx
, &request
);
3230 talloc_free(mem_ctx
);
3231 tevent_req_error(req
, ret
);
3235 header_fix_pnn(&header
, ctdb
);
3237 if (header
.destnode
>= ctdb
->node_map
->num_nodes
) {
3238 /* Many messages are not replied to, so just behave as
3239 * though this message was not received */
3240 fprintf(stderr
, "Invalid node %d\n", header
.destnode
);
3241 talloc_free(mem_ctx
);
3245 srvid
= request
.srvid
;
3246 DEBUG(DEBUG_INFO
, ("request srvid = 0x%"PRIx64
"\n", srvid
));
3248 if (srvid
== CTDB_SRVID_DISABLE_RECOVERIES
) {
3249 message_disable_recoveries(mem_ctx
, req
, &header
, &request
);
3250 } else if (srvid
== CTDB_SRVID_TAKEOVER_RUN
) {
3251 message_takeover_run(mem_ctx
, req
, &header
, &request
);
3255 talloc_free(mem_ctx
);
3258 static void client_process_control(struct tevent_req
*req
,
3259 uint8_t *buf
, size_t buflen
)
3261 struct client_state
*state
= tevent_req_data(
3262 req
, struct client_state
);
3263 struct ctdbd_context
*ctdb
= state
->ctdb
;
3264 TALLOC_CTX
*mem_ctx
;
3265 struct ctdb_req_header header
;
3266 struct ctdb_req_control request
;
3269 mem_ctx
= talloc_new(state
);
3270 if (tevent_req_nomem(mem_ctx
, req
)) {
3274 ret
= ctdb_req_control_pull(buf
, buflen
, &header
, mem_ctx
, &request
);
3276 talloc_free(mem_ctx
);
3277 tevent_req_error(req
, ret
);
3281 header_fix_pnn(&header
, ctdb
);
3283 if (header
.destnode
>= ctdb
->node_map
->num_nodes
) {
3284 struct ctdb_reply_control reply
;
3286 reply
.rdata
.opcode
= request
.opcode
;
3287 reply
.errmsg
= "Invalid node";
3289 client_send_control(req
, &header
, &reply
);
3293 DEBUG(DEBUG_INFO
, ("request opcode = %u, reqid = %u\n",
3294 request
.opcode
, header
.reqid
));
3296 if (fake_control_failure(mem_ctx
, req
, &header
, &request
)) {
3300 switch (request
.opcode
) {
3301 case CTDB_CONTROL_PROCESS_EXISTS
:
3302 control_process_exists(mem_ctx
, req
, &header
, &request
);
3305 case CTDB_CONTROL_PING
:
3306 control_ping(mem_ctx
, req
, &header
, &request
);
3309 case CTDB_CONTROL_GETDBPATH
:
3310 control_getdbpath(mem_ctx
, req
, &header
, &request
);
3313 case CTDB_CONTROL_GETVNNMAP
:
3314 control_getvnnmap(mem_ctx
, req
, &header
, &request
);
3317 case CTDB_CONTROL_GET_DEBUG
:
3318 control_get_debug(mem_ctx
, req
, &header
, &request
);
3321 case CTDB_CONTROL_SET_DEBUG
:
3322 control_set_debug(mem_ctx
, req
, &header
, &request
);
3325 case CTDB_CONTROL_GET_DBMAP
:
3326 control_get_dbmap(mem_ctx
, req
, &header
, &request
);
3329 case CTDB_CONTROL_GET_RECMODE
:
3330 control_get_recmode(mem_ctx
, req
, &header
, &request
);
3333 case CTDB_CONTROL_SET_RECMODE
:
3334 control_set_recmode(mem_ctx
, req
, &header
, &request
);
3337 case CTDB_CONTROL_REGISTER_SRVID
:
3338 control_register_srvid(mem_ctx
, req
, &header
, &request
);
3341 case CTDB_CONTROL_DEREGISTER_SRVID
:
3342 control_deregister_srvid(mem_ctx
, req
, &header
, &request
);
3345 case CTDB_CONTROL_GET_DBNAME
:
3346 control_get_dbname(mem_ctx
, req
, &header
, &request
);
3349 case CTDB_CONTROL_GET_PID
:
3350 control_get_pid(mem_ctx
, req
, &header
, &request
);
3353 case CTDB_CONTROL_GET_RECMASTER
:
3354 control_get_recmaster(mem_ctx
, req
, &header
, &request
);
3357 case CTDB_CONTROL_GET_PNN
:
3358 control_get_pnn(mem_ctx
, req
, &header
, &request
);
3361 case CTDB_CONTROL_SHUTDOWN
:
3362 control_shutdown(mem_ctx
, req
, &header
, &request
);
3365 case CTDB_CONTROL_GET_MONMODE
:
3366 control_get_monmode(mem_ctx
, req
, &header
, &request
);
3369 case CTDB_CONTROL_SET_TUNABLE
:
3370 control_set_tunable(mem_ctx
, req
, &header
, &request
);
3373 case CTDB_CONTROL_GET_TUNABLE
:
3374 control_get_tunable(mem_ctx
, req
, &header
, &request
);
3377 case CTDB_CONTROL_LIST_TUNABLES
:
3378 control_list_tunables(mem_ctx
, req
, &header
, &request
);
3381 case CTDB_CONTROL_MODIFY_FLAGS
:
3382 control_modify_flags(mem_ctx
, req
, &header
, &request
);
3385 case CTDB_CONTROL_GET_ALL_TUNABLES
:
3386 control_get_all_tunables(mem_ctx
, req
, &header
, &request
);
3389 case CTDB_CONTROL_UPTIME
:
3390 control_uptime(mem_ctx
, req
, &header
, &request
);
3393 case CTDB_CONTROL_ENABLE_MONITOR
:
3394 control_enable_monitor(mem_ctx
, req
, &header
, &request
);
3397 case CTDB_CONTROL_DISABLE_MONITOR
:
3398 control_disable_monitor(mem_ctx
, req
, &header
, &request
);
3401 case CTDB_CONTROL_RELOAD_NODES_FILE
:
3402 control_reload_nodes_file(mem_ctx
, req
, &header
, &request
);
3405 case CTDB_CONTROL_GET_CAPABILITIES
:
3406 control_get_capabilities(mem_ctx
, req
, &header
, &request
);
3409 case CTDB_CONTROL_RELEASE_IP
:
3410 control_release_ip(mem_ctx
, req
, &header
, &request
);
3413 case CTDB_CONTROL_TAKEOVER_IP
:
3414 control_takeover_ip(mem_ctx
, req
, &header
, &request
);
3417 case CTDB_CONTROL_GET_PUBLIC_IPS
:
3418 control_get_public_ips(mem_ctx
, req
, &header
, &request
);
3421 case CTDB_CONTROL_GET_NODEMAP
:
3422 control_get_nodemap(mem_ctx
, req
, &header
, &request
);
3425 case CTDB_CONTROL_GET_RECLOCK_FILE
:
3426 control_get_reclock_file(mem_ctx
, req
, &header
, &request
);
3429 case CTDB_CONTROL_STOP_NODE
:
3430 control_stop_node(mem_ctx
, req
, &header
, &request
);
3433 case CTDB_CONTROL_CONTINUE_NODE
:
3434 control_continue_node(mem_ctx
, req
, &header
, &request
);
3437 case CTDB_CONTROL_SET_BAN_STATE
:
3438 control_set_ban_state(mem_ctx
, req
, &header
, &request
);
3441 case CTDB_CONTROL_GET_DB_SEQNUM
:
3442 control_get_db_seqnum(mem_ctx
, req
, &header
, &request
);
3445 case CTDB_CONTROL_DB_GET_HEALTH
:
3446 control_db_get_health(mem_ctx
, req
, &header
, &request
);
3449 case CTDB_CONTROL_GET_PUBLIC_IP_INFO
:
3450 control_get_public_ip_info(mem_ctx
, req
, &header
, &request
);
3453 case CTDB_CONTROL_GET_IFACES
:
3454 control_get_ifaces(mem_ctx
, req
, &header
, &request
);
3457 case CTDB_CONTROL_SET_IFACE_LINK_STATE
:
3458 control_set_iface_link_state(mem_ctx
, req
, &header
, &request
);
3461 case CTDB_CONTROL_SET_DB_READONLY
:
3462 control_set_db_readonly(mem_ctx
, req
, &header
, &request
);
3465 case CTDB_CONTROL_SET_DB_STICKY
:
3466 control_set_db_sticky(mem_ctx
, req
, &header
, &request
);
3469 case CTDB_CONTROL_IPREALLOCATED
:
3470 control_ipreallocated(mem_ctx
, req
, &header
, &request
);
3473 case CTDB_CONTROL_GET_RUNSTATE
:
3474 control_get_runstate(mem_ctx
, req
, &header
, &request
);
3477 case CTDB_CONTROL_GET_NODES_FILE
:
3478 control_get_nodes_file(mem_ctx
, req
, &header
, &request
);
3481 case CTDB_CONTROL_CHECK_PID_SRVID
:
3482 control_check_pid_srvid(mem_ctx
, req
, &header
, &request
);
3486 if (! (request
.flags
& CTDB_CTRL_FLAG_NOREPLY
)) {
3487 control_error(mem_ctx
, req
, &header
, &request
);
3493 talloc_free(mem_ctx
);
3496 static int client_recv(struct tevent_req
*req
, int *perr
)
3498 struct client_state
*state
= tevent_req_data(
3499 req
, struct client_state
);
3502 DEBUG(DEBUG_INFO
, ("Client done fd=%d\n", state
->fd
));
3505 if (tevent_req_is_unix_error(req
, &err
)) {
3512 return state
->status
;
3519 struct server_state
{
3520 struct tevent_context
*ev
;
3521 struct ctdbd_context
*ctdb
;
3525 static void server_new_client(struct tevent_req
*subreq
);
3526 static void server_client_done(struct tevent_req
*subreq
);
3528 static struct tevent_req
*server_send(TALLOC_CTX
*mem_ctx
,
3529 struct tevent_context
*ev
,
3530 struct ctdbd_context
*ctdb
,
3533 struct tevent_req
*req
, *subreq
;
3534 struct server_state
*state
;
3536 req
= tevent_req_create(mem_ctx
, &state
, struct server_state
);
3545 subreq
= accept_send(state
, ev
, fd
);
3546 if (tevent_req_nomem(subreq
, req
)) {
3547 return tevent_req_post(req
, ev
);
3549 tevent_req_set_callback(subreq
, server_new_client
, req
);
3554 static void server_new_client(struct tevent_req
*subreq
)
3556 struct tevent_req
*req
= tevent_req_callback_data(
3557 subreq
, struct tevent_req
);
3558 struct server_state
*state
= tevent_req_data(
3559 req
, struct server_state
);
3560 struct ctdbd_context
*ctdb
= state
->ctdb
;
3564 client_fd
= accept_recv(subreq
, NULL
, NULL
, &ret
);
3565 TALLOC_FREE(subreq
);
3566 if (client_fd
== -1) {
3567 tevent_req_error(req
, ret
);
3571 subreq
= client_send(state
, state
->ev
, client_fd
,
3572 ctdb
, ctdb
->node_map
->pnn
);
3573 if (tevent_req_nomem(subreq
, req
)) {
3576 tevent_req_set_callback(subreq
, server_client_done
, req
);
3578 ctdb
->num_clients
+= 1;
3580 subreq
= accept_send(state
, state
->ev
, state
->fd
);
3581 if (tevent_req_nomem(subreq
, req
)) {
3584 tevent_req_set_callback(subreq
, server_new_client
, req
);
3587 static void server_client_done(struct tevent_req
*subreq
)
3589 struct tevent_req
*req
= tevent_req_callback_data(
3590 subreq
, struct tevent_req
);
3591 struct server_state
*state
= tevent_req_data(
3592 req
, struct server_state
);
3593 struct ctdbd_context
*ctdb
= state
->ctdb
;
3597 status
= client_recv(subreq
, &ret
);
3598 TALLOC_FREE(subreq
);
3600 tevent_req_error(req
, ret
);
3604 ctdb
->num_clients
-= 1;
3607 /* Special status, to shutdown server */
3608 DEBUG(DEBUG_INFO
, ("Shutting down server\n"));
3609 tevent_req_done(req
);
3613 static bool server_recv(struct tevent_req
*req
, int *perr
)
3617 if (tevent_req_is_unix_error(req
, &err
)) {
3630 static int socket_init(const char *sockpath
)
3632 struct sockaddr_un addr
;
3636 memset(&addr
, 0, sizeof(addr
));
3637 addr
.sun_family
= AF_UNIX
;
3639 len
= strlcpy(addr
.sun_path
, sockpath
, sizeof(addr
.sun_path
));
3640 if (len
>= sizeof(addr
.sun_path
)) {
3641 fprintf(stderr
, "path too long: %s\n", sockpath
);
3645 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
3647 fprintf(stderr
, "socket failed - %s\n", sockpath
);
3651 ret
= bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
));
3653 fprintf(stderr
, "bind failed - %s\n", sockpath
);
3657 ret
= listen(fd
, 10);
3659 fprintf(stderr
, "listen failed\n");
3663 DEBUG(DEBUG_INFO
, ("Socket init done\n"));
3674 static struct options
{
3675 const char *sockpath
;
3676 const char *pidfile
;
3677 const char *debuglevel
;
3680 static struct poptOption cmdline_options
[] = {
3681 { "socket", 's', POPT_ARG_STRING
, &options
.sockpath
, 0,
3682 "Unix domain socket path", "filename" },
3683 { "pidfile", 'p', POPT_ARG_STRING
, &options
.pidfile
, 0,
3684 "pid file", "filename" } ,
3685 { "debug", 'd', POPT_ARG_STRING
, &options
.debuglevel
, 0,
3686 "debug level", "ERR|WARNING|NOTICE|INFO|DEBUG" } ,
3689 static void cleanup(void)
3691 unlink(options
.sockpath
);
3692 unlink(options
.pidfile
);
3695 static void signal_handler(int sig
)
3701 static void start_server(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3702 struct ctdbd_context
*ctdb
, int fd
, int pfd
)
3704 struct tevent_req
*req
;
3709 signal(SIGTERM
, signal_handler
);
3711 req
= server_send(mem_ctx
, ev
, ctdb
, fd
);
3713 fprintf(stderr
, "Memory error\n");
3717 len
= write(pfd
, &ret
, sizeof(ret
));
3718 if (len
!= sizeof(ret
)) {
3719 fprintf(stderr
, "Failed to send message to parent\n");
3724 tevent_req_poll(req
, ev
);
3726 server_recv(req
, &ret
);
3732 int main(int argc
, const char *argv
[])
3734 TALLOC_CTX
*mem_ctx
;
3735 struct ctdbd_context
*ctdb
;
3736 struct tevent_context
*ev
;
3738 int opt
, fd
, ret
, pfd
[2];
3743 pc
= poptGetContext(argv
[0], argc
, argv
, cmdline_options
,
3744 POPT_CONTEXT_KEEP_FIRST
);
3745 while ((opt
= poptGetNextOpt(pc
)) != -1) {
3746 fprintf(stderr
, "Invalid option %s\n", poptBadOption(pc
, 0));
3750 if (options
.sockpath
== NULL
) {
3751 fprintf(stderr
, "Please specify socket path\n");
3752 poptPrintHelp(pc
, stdout
, 0);
3756 if (options
.pidfile
== NULL
) {
3757 fprintf(stderr
, "Please specify pid file\n");
3758 poptPrintHelp(pc
, stdout
, 0);
3762 mem_ctx
= talloc_new(NULL
);
3763 if (mem_ctx
== NULL
) {
3764 fprintf(stderr
, "Memory error\n");
3768 ret
= logging_init(mem_ctx
, "file:", options
.debuglevel
, "fake-ctdbd");
3770 fprintf(stderr
, "Invalid debug level\n");
3771 poptPrintHelp(pc
, stdout
, 0);
3775 ctdb
= ctdbd_setup(mem_ctx
);
3780 if (! ctdbd_verify(ctdb
)) {
3784 ev
= tevent_context_init(mem_ctx
);
3786 fprintf(stderr
, "Memory error\n");
3790 fd
= socket_init(options
.sockpath
);
3797 fprintf(stderr
, "Failed to create pipe\n");
3804 fprintf(stderr
, "Failed to fork\n");
3812 start_server(mem_ctx
, ev
, ctdb
, fd
, pfd
[1]);
3819 len
= read(pfd
[0], &ret
, sizeof(ret
));
3821 if (len
!= sizeof(ret
)) {
3822 fprintf(stderr
, "len = %zi\n", len
);
3823 fprintf(stderr
, "Failed to get message from child\n");
3828 fp
= fopen(options
.pidfile
, "w");
3830 fprintf(stderr
, "Failed to open pid file %s\n",
3835 fprintf(fp
, "%d\n", pid
);