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