ctdb-daemon: Rename struct ctdb_node_map to ctdb_node_map_old
[Samba.git] / ctdb / tests / src / ctdb_test_stubs.c
blob3a04c170aaa07c5d2ee9b08ec940e54e6b246242
1 /*
2 Test stubs and support functions for some CTDB client functions
4 Copyright (C) Martin Schwenke 2011
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/>.
20 /* Useful for functions that don't get struct ctdb_context passed */
21 static struct ctdb_context *ctdb_global;
23 static struct ctdb_node_capabilities *global_caps = NULL;
25 /* Read a nodemap from stdin. Each line looks like:
26 * <PNN> <FLAGS> [RECMASTER] [CURRENT] [CAPABILITIES]
27 * EOF or a blank line terminates input.
29 * By default, capablities for each node are
30 * CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER|CTDB_CAP_NATGW. These 3
31 * capabilities can be faked off by adding, for example,
32 * -CTDB_CAP_RECMASTER. LVS can be faked on by adding
33 * CTDB_CAP_LVS.
36 /* A fake flag that is only supported by some functions */
37 #define NODE_FLAGS_FAKE_TIMEOUT 0x80000000
39 static void ctdb_test_stubs_read_nodemap(struct ctdb_context *ctdb)
41 char line[1024];
43 TALLOC_FREE(ctdb->nodes);
44 ctdb->pnn = -1;
45 ctdb->num_nodes = 0;
47 ctdb->nodes = NULL;
49 while ((fgets(line, sizeof(line), stdin) != NULL) &&
50 (line[0] != '\n')) {
51 uint32_t pnn, flags, capabilities;
52 char *tok, *t;
53 char *ip;
54 ctdb_sock_addr saddr;
56 /* Get rid of pesky newline */
57 if ((t = strchr(line, '\n')) != NULL) {
58 *t = '\0';
61 /* Get PNN */
62 tok = strtok(line, " \t");
63 if (tok == NULL) {
64 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (PNN) ignored \"%s\"\n", line));
65 continue;
67 pnn = (uint32_t)strtoul(tok, NULL, 0);
69 /* Get IP */
70 tok = strtok(NULL, " \t");
71 if (tok == NULL) {
72 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (no IP) ignored \"%s\"\n", line));
73 continue;
75 if (!parse_ip(tok, NULL, 0, &saddr)) {
76 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (IP) ignored \"%s\"\n", line));
77 continue;
79 ip = talloc_strdup(ctdb, tok);
81 /* Get flags */
82 tok = strtok(NULL, " \t");
83 if (tok == NULL) {
84 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line (flags) ignored \"%s\"\n", line));
85 continue;
87 flags = (uint32_t)strtoul(tok, NULL, 0);
88 /* Handle deleted nodes */
89 if (flags & NODE_FLAGS_DELETED) {
90 talloc_free(ip);
91 ip = talloc_strdup(ctdb, "0.0.0.0");
93 capabilities = CTDB_CAP_RECMASTER|CTDB_CAP_LMASTER|CTDB_CAP_NATGW;
95 tok = strtok(NULL, " \t");
96 while (tok != NULL) {
97 if (strcmp(tok, "CURRENT") == 0) {
98 ctdb->pnn = pnn;
99 } else if (strcmp(tok, "RECMASTER") == 0) {
100 ctdb->recovery_master = pnn;
101 } else if (strcmp(tok, "-CTDB_CAP_RECMASTER") == 0) {
102 capabilities &= ~CTDB_CAP_RECMASTER;
103 } else if (strcmp(tok, "-CTDB_CAP_LMASTER") == 0) {
104 capabilities &= ~CTDB_CAP_LMASTER;
105 } else if (strcmp(tok, "-CTDB_CAP_NATGW") == 0) {
106 capabilities &= ~CTDB_CAP_NATGW;
107 } else if (strcmp(tok, "CTDB_CAP_LVS") == 0) {
108 capabilities |= CTDB_CAP_LVS;
109 } else if (strcmp(tok, "TIMEOUT") == 0) {
110 /* This can be done with just a flag
111 * value but it is probably clearer
112 * and less error-prone to fake this
113 * with an explicit token */
114 flags |= NODE_FLAGS_FAKE_TIMEOUT;
116 tok = strtok(NULL, " \t");
119 ctdb->nodes = talloc_realloc(ctdb, ctdb->nodes, struct ctdb_node *, ctdb->num_nodes + 1);
120 if (ctdb->nodes == NULL) {
121 DEBUG(DEBUG_ERR, ("OOM allocating nodes array\n"));
122 exit (1);
124 ctdb->nodes[ctdb->num_nodes] = talloc_zero(ctdb, struct ctdb_node);
125 if (ctdb->nodes[ctdb->num_nodes] == NULL) {
126 DEBUG(DEBUG_ERR, ("OOM allocating node structure\n"));
127 exit (1);
130 ctdb->nodes[ctdb->num_nodes]->ctdb = ctdb;
131 ctdb->nodes[ctdb->num_nodes]->name = "fakectdb";
132 ctdb->nodes[ctdb->num_nodes]->pnn = pnn;
133 parse_ip(ip, NULL, 0, &ctdb->nodes[ctdb->num_nodes]->address);
134 ctdb->nodes[ctdb->num_nodes]->flags = flags;
136 global_caps = talloc_realloc(ctdb, global_caps,
137 struct ctdb_node_capabilities,
138 ctdb->num_nodes+1);
139 global_caps[ctdb->num_nodes].capabilities = capabilities;
140 global_caps[ctdb->num_nodes].retrieved = true;
142 ctdb->num_nodes++;
146 static void assert_nodes_set(struct ctdb_context *ctdb)
148 if (ctdb->nodes == NULL) {
149 printf("ctdb->nodes not initialised - missing a NODEMAP section?");
150 exit(1);
154 #ifdef CTDB_TEST_OVERRIDE_MAIN
155 static void ctdb_test_stubs_print_nodemap(struct ctdb_context *ctdb)
157 int i;
159 assert_nodes_set(ctdb);
161 for (i = 0; i < ctdb->num_nodes; i++) {
162 printf("%ld\t0x%lx%s%s\n",
163 (unsigned long) ctdb->nodes[i]->pnn,
164 (unsigned long) ctdb->nodes[i]->flags,
165 ctdb->nodes[i]->pnn == ctdb->pnn ? "\tCURRENT" : "",
166 ctdb->nodes[i]->pnn == ctdb->recovery_master ? "\tRECMASTER" : "");
169 #endif
171 /* Read interfaces information. Same format as "ctdb ifaces -Y"
172 * output:
173 * :Name:LinkStatus:References:
174 * :eth2:1:4294967294
175 * :eth1:1:4294967292
178 struct ctdb_iface {
179 struct ctdb_iface *prev, *next;
180 const char *name;
181 bool link_up;
182 uint32_t references;
185 static void ctdb_test_stubs_read_ifaces(struct ctdb_context *ctdb)
187 char line[1024];
188 struct ctdb_iface *iface;
190 while ((fgets(line, sizeof(line), stdin) != NULL) &&
191 (line[0] != '\n')) {
192 uint16_t link_state;
193 uint32_t references;
194 char *tok, *t, *name;
196 /* Get rid of pesky newline */
197 if ((t = strchr(line, '\n')) != NULL) {
198 *t = '\0';
201 if (strcmp(line, ":Name:LinkStatus:References:") == 0) {
202 continue;
205 /* name */
206 //tok = strtok(line, ":"); /* Leading colon... */
207 tok = strtok(line, ":");
208 if (tok == NULL) {
209 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line ignored \"%s\"\n", line));
210 continue;
212 name = tok;
214 /* link_state */
215 tok = strtok(NULL, ":");
216 if (tok == NULL) {
217 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line ignored \"%s\"\n", line));
218 continue;
220 link_state = (uint16_t)strtoul(tok, NULL, 0);
222 /* references... */
223 tok = strtok(NULL, ":");
224 if (tok == NULL) {
225 DEBUG(DEBUG_ERR, (__location__ " WARNING, bad line ignored \"%s\"\n", line));
226 continue;
228 references = (uint32_t)strtoul(tok, NULL, 0);
230 iface = talloc_zero(ctdb, struct ctdb_iface);
232 if (iface == NULL) {
233 DEBUG(DEBUG_ERR, ("OOM allocating iface\n"));
234 exit (1);
237 iface->name = talloc_strdup(iface, name);
238 iface->link_up = link_state;
239 iface->references = references;
241 DLIST_ADD(ctdb->ifaces, iface);
245 static void assert_ifaces_set(struct ctdb_context *ctdb)
247 if (ctdb->ifaces == NULL) {
248 printf("ctdb->ifaces not initialised - missing an IFACES section?");
249 exit(1);
253 #ifdef CTDB_TEST_OVERRIDE_MAIN
254 static void ctdb_test_stubs_print_ifaces(struct ctdb_context *ctdb)
256 struct ctdb_iface *iface;
258 assert_ifaces_set(ctdb);
260 printf(":Name:LinkStatus:References:\n");
261 for (iface = ctdb->ifaces; iface != NULL; iface = iface->next) {
262 printf(":%s:%u:%u:\n",
263 iface->name,
264 iface->link_up,
265 iface->references);
268 #endif
270 /* Read vnn map.
271 * output:
272 * <GENERATION>
273 * <LMASTER0>
274 * <LMASTER1>
275 * ...
279 struct ctdb_vnn_map {
280 uint32_t generation;
281 uint32_t size;
282 uint32_t *map;
285 static void ctdb_test_stubs_read_vnnmap(struct ctdb_context *ctdb)
287 char line[1024];
289 TALLOC_FREE(ctdb->vnn_map);
291 ctdb->vnn_map = talloc_zero(ctdb, struct ctdb_vnn_map);
292 if (ctdb->vnn_map == NULL) {
293 DEBUG(DEBUG_ERR, ("OOM allocating vnnmap\n"));
294 exit (1);
296 ctdb->vnn_map->generation = INVALID_GENERATION;
297 ctdb->vnn_map->size = 0;
298 ctdb->vnn_map->map = NULL;
300 while ((fgets(line, sizeof(line), stdin) != NULL) &&
301 (line[0] != '\n')) {
302 uint32_t n;
303 char *t;
305 /* Get rid of pesky newline */
306 if ((t = strchr(line, '\n')) != NULL) {
307 *t = '\0';
310 n = (uint32_t) strtol(line, NULL, 0);
312 /* generation */
313 if (ctdb->vnn_map->generation == INVALID_GENERATION) {
314 ctdb->vnn_map->generation = n;
315 continue;
318 ctdb->vnn_map->map = talloc_realloc(ctdb, ctdb->vnn_map->map, uint32_t, ctdb->vnn_map->size + 1);
319 if (ctdb->vnn_map->map == NULL) {
320 DEBUG(DEBUG_ERR, ("OOM allocating vnn_map->map\n"));
321 exit (1);
324 ctdb->vnn_map->map[ctdb->vnn_map->size] = n;
325 ctdb->vnn_map->size++;
329 static void assert_vnn_map_set(struct ctdb_context *ctdb)
331 if (ctdb->vnn_map == NULL) {
332 printf("ctdb->vnn_map not initialised - missing a VNNMAP section?");
333 exit(1);
337 #ifdef CTDB_TEST_OVERRIDE_MAIN
338 static void ctdb_test_stubs_print_vnnmap(struct ctdb_context *ctdb)
340 int i;
342 assert_vnn_map_set(ctdb);
344 printf("%d\n", ctdb->vnn_map->generation);
345 for (i = 0; i < ctdb->vnn_map->size; i++) {
346 printf("%d\n", ctdb->vnn_map->map[i]);
349 #endif
351 static void ctdb_test_stubs_fake_setup(struct ctdb_context *ctdb)
353 char line[1024];
355 while (fgets(line, sizeof(line), stdin) != NULL) {
356 char *t;
358 /* Get rid of pesky newline */
359 if ((t = strchr(line, '\n')) != NULL) {
360 *t = '\0';
363 if (strcmp(line, "NODEMAP") == 0) {
364 ctdb_test_stubs_read_nodemap(ctdb);
365 } else if (strcmp(line, "IFACES") == 0) {
366 ctdb_test_stubs_read_ifaces(ctdb);
367 } else if (strcmp(line, "VNNMAP") == 0) {
368 ctdb_test_stubs_read_vnnmap(ctdb);
369 } else {
370 printf("Unknown line %s\n", line);
371 exit(1);
376 /* Support... */
377 static bool current_node_is_connected (struct ctdb_context *ctdb)
379 int i;
381 assert_nodes_set(ctdb);
383 for (i = 0; i < ctdb->num_nodes; i++) {
384 if (ctdb->nodes[i]->pnn == ctdb->pnn) {
385 if (ctdb->nodes[i]->flags &
386 (NODE_FLAGS_DISCONNECTED | NODE_FLAGS_DELETED)) {
387 return false;
388 } else {
389 return true;
394 /* Shouldn't really happen, so fag an error */
395 return false;
398 /* Stubs... */
400 struct ctdb_context *ctdb_cmdline_client_stub(struct tevent_context *ev,
401 struct timeval req_timeout)
403 const char *t = getenv("CTDB_DEBUGLEVEL");
404 if (t != NULL) {
405 DEBUGLEVEL= atoi(t);
406 } else {
407 DEBUGLEVEL = 0;
410 ctdb_global->ev = ev;
412 return ctdb_global;
415 struct tevent_context *tevent_context_init_stub(TALLOC_CTX *mem_ctx)
417 struct ctdb_context *ctdb;
419 /* This needs to be initialised prior to the client setup, for
420 the xpnn stub */
421 ctdb = talloc_zero(NULL, struct ctdb_context);
423 ctdb_set_socketname(ctdb, "fake");
425 ctdb_test_stubs_fake_setup(ctdb);
427 ctdb_global = ctdb;
429 return tevent_context_init_byname(mem_ctx, NULL);
433 ctdb_ctrl_getnodemap_stub(struct ctdb_context *ctdb,
434 struct timeval timeout, uint32_t destnode,
435 TALLOC_CTX *mem_ctx,
436 struct ctdb_node_map_old **nodemap)
438 assert_nodes_set(ctdb);
440 if (!current_node_is_connected(ctdb)) {
441 return -1;
444 *nodemap = ctdb_node_list_to_map(ctdb->nodes, ctdb->num_nodes,
445 mem_ctx);
447 return 0;
451 ctdb_ctrl_getnodesfile_stub(struct ctdb_context *ctdb,
452 struct timeval timeout, uint32_t destnode,
453 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
455 char *v, *f;
457 /* If there's an environment variable for a node-specific file
458 * then use it. Otherwise use the global file. */
459 v = talloc_asprintf(mem_ctx, "CTDB_NODES_%u", destnode);
460 f = getenv(v);
461 if (f == NULL) {
462 f = getenv("CTDB_NODES");
465 *nodemap = ctdb_read_nodes_file(mem_ctx, f);
467 return *nodemap == NULL ? -1 : 0;
471 ctdb_ctrl_getvnnmap_stub(struct ctdb_context *ctdb,
472 struct timeval timeout, uint32_t destnode,
473 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
475 assert_vnn_map_set(ctdb);
477 *vnnmap = talloc(ctdb, struct ctdb_vnn_map);
478 if (*vnnmap == NULL) {
479 DEBUG(DEBUG_ERR, (__location__ "OOM\n"));
480 exit (1);
482 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, ctdb->vnn_map->size);
484 (*vnnmap)->generation = ctdb->vnn_map->generation;
485 (*vnnmap)->size = ctdb->vnn_map->size;
486 memcpy((*vnnmap)->map, ctdb->vnn_map->map, sizeof(uint32_t) * (*vnnmap)->size);
488 return 0;
492 ctdb_ctrl_getrecmode_stub(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
493 struct timeval timeout, uint32_t destnode,
494 uint32_t *recmode)
496 *recmode = ctdb->recovery_mode;
498 return 0;
501 int ctdb_ctrl_setrecmode_stub(struct ctdb_context *ctdb, struct timeval timeout,
502 uint32_t destnode, uint32_t recmode)
504 ctdb->recovery_mode = recmode;
506 if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE) {
507 /* Recovery is complete! That was quick.... */
508 ctdb->recovery_mode = CTDB_RECOVERY_NORMAL;
509 assert_vnn_map_set(ctdb);
510 ctdb->vnn_map->generation++;
513 return 0;
517 ctdb_ctrl_getrecmaster_stub(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
518 struct timeval timeout, uint32_t destnode,
519 uint32_t *recmaster)
521 *recmaster = ctdb->recovery_master;
523 return 0;
527 ctdb_ctrl_getpnn_stub(struct ctdb_context *ctdb, struct timeval timeout,
528 uint32_t destnode)
530 if (!current_node_is_connected(ctdb)) {
531 return -1;
534 if (destnode == CTDB_CURRENT_NODE) {
535 return ctdb->pnn;
536 } else {
537 return destnode;
541 /* From ctdb_takeover.c */
542 int32_t ctdb_control_get_ifaces(struct ctdb_context *ctdb,
543 struct ctdb_req_control_old *c,
544 TDB_DATA *outdata)
546 int i, num, len;
547 struct ctdb_control_get_ifaces *ifaces;
548 struct ctdb_iface *cur;
550 assert_ifaces_set(ctdb);
552 /* count how many public ip structures we have */
553 num = 0;
554 for (cur=ctdb->ifaces;cur;cur=cur->next) {
555 num++;
558 len = offsetof(struct ctdb_control_get_ifaces, ifaces) +
559 num*sizeof(struct ctdb_control_iface_info);
560 ifaces = talloc_zero_size(outdata, len);
561 CTDB_NO_MEMORY(ctdb, ifaces);
563 i = 0;
564 for (cur=ctdb->ifaces;cur;cur=cur->next) {
565 size_t nlen = strlcpy(ifaces->ifaces[i].name, cur->name,
566 sizeof(ifaces->ifaces[i].name));
567 if (nlen >= sizeof(ifaces->ifaces[i].name)) {
568 /* Ignore invalid name */
569 continue;
571 ifaces->ifaces[i].link_state = cur->link_up;
572 ifaces->ifaces[i].references = cur->references;
573 i++;
575 ifaces->num = i;
576 len = offsetof(struct ctdb_control_get_ifaces, ifaces) +
577 i*sizeof(struct ctdb_control_iface_info);
579 outdata->dsize = len;
580 outdata->dptr = (uint8_t *)ifaces;
582 return 0;
586 ctdb_ctrl_get_ifaces_stub(struct ctdb_context *ctdb,
587 struct timeval timeout, uint32_t destnode,
588 TALLOC_CTX *mem_ctx,
589 struct ctdb_control_get_ifaces **ifaces)
591 TDB_DATA *outdata;
592 int ret;
594 if (!current_node_is_connected(ctdb)) {
595 return -1;
598 outdata = talloc(mem_ctx, TDB_DATA);
600 ret = ctdb_control_get_ifaces(ctdb, NULL, outdata);
602 if (ret == 0) {
603 *ifaces = (struct ctdb_control_get_ifaces *)outdata->dptr;
606 return ret;
609 /* In reality handlers can be registered for many srvids. However,
610 * the ctdb tool only registers one at a time so keep this simple. */
611 static struct {
612 uint64_t srvid;
613 srvid_handler_fn message_handler;
614 void *message_private;
615 } ctdb_message_list_fake = {
616 .srvid = 0,
617 .message_handler = NULL,
618 .message_private = NULL,
621 int ctdb_client_set_message_handler_stub(struct ctdb_context *ctdb,
622 uint64_t srvid,
623 srvid_handler_fn handler,
624 void *private_data)
626 ctdb_message_list_fake.srvid = srvid;
627 ctdb_message_list_fake.message_handler = handler;
628 ctdb_message_list_fake.message_private = private_data;
630 return 0;
633 int ctdb_client_remove_message_handler_stub(struct ctdb_context *ctdb,
634 uint64_t srvid,
635 void *private_data)
637 ctdb_message_list_fake.srvid = 0;
638 ctdb_message_list_fake.message_handler = NULL;
639 ctdb_message_list_fake.message_private = NULL;
641 return 0;
644 static void ctdb_fake_handler_pnn_reply(struct ctdb_context *ctdb,
645 uint32_t pnn)
647 TDB_DATA reply_data;
649 reply_data.dsize = sizeof(pnn);
650 reply_data.dptr = (uint8_t *)&pnn;
651 ctdb_message_list_fake.message_handler(
652 ctdb_message_list_fake.srvid,
653 reply_data,
654 ctdb_message_list_fake.message_private);
657 int ctdb_client_send_message_stub(struct ctdb_context *ctdb,
658 uint32_t pnn,
659 uint64_t srvid, TDB_DATA data)
661 struct srvid_reply_handler_data *d;
662 int i;
664 if (ctdb_message_list_fake.message_handler == NULL) {
665 DEBUG(DEBUG_ERR,
666 (__location__
667 " no message handler registered for srvid %llu\n",
668 (unsigned long long)srvid));
669 return -1;
672 switch (srvid) {
673 case CTDB_SRVID_TAKEOVER_RUN:
674 /* Fake a single reply from recovery master */
675 DEBUG(DEBUG_NOTICE,
676 ("Fake takeover run on recovery master %u\n",
677 ctdb->recovery_master));
678 ctdb_fake_handler_pnn_reply(ctdb, ctdb->recovery_master);
679 break;
681 case CTDB_SRVID_DISABLE_RECOVERIES:
682 case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
683 /* Assume srvid_broadcast() is in use and reply on
684 * behalf of relevant nodes */
685 if (pnn != CTDB_BROADCAST_CONNECTED) {
686 DEBUG(DEBUG_ERR,
687 (__location__
688 " srvid %llu must use pnn CTDB_BROADCAST_CONNECTED\n",
689 (unsigned long long)srvid));
690 return -1;
693 d = (struct srvid_reply_handler_data *)ctdb_message_list_fake.message_private;
694 if (d == NULL) {
695 DEBUG(DEBUG_ERR,
696 (__location__ " No private data registered\n"));
697 return -1;
699 if (d->nodes == NULL) {
700 DEBUG(DEBUG_ERR,
701 (__location__
702 " No nodes to reply to in private data\n"));
703 return -1;
706 for (i = 0; i < talloc_array_length(d->nodes); i++) {
707 if (d->nodes[i] != -1) {
708 ctdb_fake_handler_pnn_reply(ctdb, d->nodes[i]);
711 break;
713 default:
714 DEBUG(DEBUG_ERR,
715 (__location__ " srvid %llu not implemented\n",
716 (unsigned long long)srvid));
717 return -1;
720 return 0;
723 int ctdb_client_check_message_handlers_stub(struct ctdb_context *ctdb,
724 uint64_t *ids, uint32_t num,
725 uint8_t *result)
727 DEBUG(DEBUG_ERR, (__location__ " NOT IMPLEMENTED\n"));
728 return -1;
731 int ctdb_ctrl_getcapabilities_stub(struct ctdb_context *ctdb,
732 struct timeval timeout, uint32_t destnode,
733 uint32_t *capabilities)
735 uint32_t *capp;
737 assert_nodes_set(ctdb);
739 if (ctdb->nodes[destnode]->flags & NODE_FLAGS_FAKE_TIMEOUT) {
740 /* Placeholder for line#, instead of __location__ */
741 DEBUG(DEBUG_ERR,
742 ("__LOCATION__ control timed out."
743 " reqid:1234567890 opcode:80 dstnode:%d\n", destnode));
744 DEBUG(DEBUG_ERR,
745 ("__LOCATION__ ctdb_control_recv failed\n"));
746 DEBUG(DEBUG_ERR,
747 ("__LOCATION__ ctdb_ctrl_getcapabilities_recv failed\n"));
748 return -1;
751 if (ctdb->nodes[destnode]->flags & NODE_FLAGS_DISCONNECTED) {
752 DEBUG(DEBUG_ERR,
753 ("ctdb_control error: 'ctdb_control to disconnected node\n"));
754 /* Placeholder for line#, instead of __location__ */
755 DEBUG(DEBUG_ERR,
756 ("__LOCATION__ ctdb_ctrl_getcapabilities_recv failed\n"));
757 return -1;
760 capp = ctdb_get_node_capabilities(global_caps, destnode);
761 if (capp == NULL) {
762 DEBUG(DEBUG_ERR, ("__LOCATION__ invalid PNN\n"));
763 return -1;
765 *capabilities = *capp;
766 return 0;
769 int ctdb_ctrl_reload_nodes_file_stub(struct ctdb_context *ctdb,
770 struct timeval timeout, uint32_t destnode)
772 DEBUG(DEBUG_NOTICE, ("ctdb_ctrl_reload_nodes_file: node %u\n", destnode));
773 return 0;
776 /* This is to support testing ctdb xpnn */
778 bool ctdb_sys_have_ip_stub(ctdb_sock_addr *addr)
780 int i;
781 struct ctdb_context *ctdb = ctdb_global;
783 assert_nodes_set(ctdb);
785 for (i = 0; i < ctdb->num_nodes; i++) {
786 if (ctdb->pnn == ctdb->nodes[i]->pnn) {
787 if (ctdb_same_ip(addr, &ctdb->nodes[i]->address)) {
788 return true;
793 return false;
797 ctdb_client_async_control_stub(struct ctdb_context *ctdb,
798 enum ctdb_controls opcode,
799 uint32_t *nodes,
800 uint64_t srvid,
801 struct timeval timeout,
802 bool dont_log_errors,
803 TDB_DATA data,
804 client_async_callback client_callback,
805 client_async_callback fail_callback,
806 void *callback_data)
808 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
809 int i, ret;
811 ret = 0;
812 for (i = 0; i < talloc_array_length(nodes); i++) {
813 uint32_t pnn = nodes[i];
814 TDB_DATA outdata;
815 int res;
817 /* Not so async... but good enough for testing! */
818 switch (opcode) {
819 case CTDB_CONTROL_RELOAD_NODES_FILE:
820 res = ctdb_ctrl_reload_nodes_file_stub(ctdb, timeout, pnn);
821 break;
822 case CTDB_CONTROL_RELOAD_PUBLIC_IPS:
823 DEBUG(DEBUG_NOTICE, ("Fake reload public IPs on node %u\n", pnn));
824 res = 0;
825 break;
826 case CTDB_CONTROL_GET_NODES_FILE: {
827 struct ctdb_node_map_old *nodemap;
828 res = ctdb_ctrl_getnodesfile_stub(ctdb, timeout, pnn,
829 tmp_ctx, &nodemap);
830 if (res == 0) {
831 outdata.dsize = talloc_get_size(nodemap);
832 outdata.dptr = (uint8_t *) nodemap;
835 break;
836 default:
837 DEBUG(DEBUG_ERR, (__location__ " Control not implemented %u\n",
838 opcode));
839 talloc_free(tmp_ctx);
840 return -1;
843 if (res == 0) {
844 if (client_callback != NULL) {
845 client_callback(ctdb, pnn, res, outdata, callback_data);
847 } else {
848 ret = -1;
849 if (fail_callback != NULL) {
850 fail_callback(ctdb, pnn, res, outdata, callback_data);
855 talloc_free(tmp_ctx);
856 return ret;
859 struct ctdb_node_capabilities *
860 ctdb_get_capabilities_stub(struct ctdb_context *ctdb,
861 TALLOC_CTX *mem_ctx,
862 struct timeval timeout,
863 struct ctdb_node_map_old *nodemap)
865 return global_caps;