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
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
)
43 TALLOC_FREE(ctdb
->nodes
);
49 while ((fgets(line
, sizeof(line
), stdin
) != NULL
) &&
51 uint32_t pnn
, flags
, capabilities
;
56 /* Get rid of pesky newline */
57 if ((t
= strchr(line
, '\n')) != NULL
) {
62 tok
= strtok(line
, " \t");
64 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (PNN) ignored \"%s\"\n", line
));
67 pnn
= (uint32_t)strtoul(tok
, NULL
, 0);
70 tok
= strtok(NULL
, " \t");
72 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (no IP) ignored \"%s\"\n", line
));
75 if (!parse_ip(tok
, NULL
, 0, &saddr
)) {
76 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (IP) ignored \"%s\"\n", line
));
79 ip
= talloc_strdup(ctdb
, tok
);
82 tok
= strtok(NULL
, " \t");
84 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line (flags) ignored \"%s\"\n", line
));
87 flags
= (uint32_t)strtoul(tok
, NULL
, 0);
88 /* Handle deleted nodes */
89 if (flags
& NODE_FLAGS_DELETED
) {
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");
97 if (strcmp(tok
, "CURRENT") == 0) {
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"));
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"));
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
,
139 global_caps
[ctdb
->num_nodes
].capabilities
= capabilities
;
140 global_caps
[ctdb
->num_nodes
].retrieved
= true;
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?");
154 #ifdef CTDB_TEST_OVERRIDE_MAIN
155 static void ctdb_test_stubs_print_nodemap(struct ctdb_context
*ctdb
)
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" : "");
171 /* Read interfaces information. Same format as "ctdb ifaces -Y"
173 * :Name:LinkStatus:References:
179 struct ctdb_iface
*prev
, *next
;
185 static void ctdb_test_stubs_read_ifaces(struct ctdb_context
*ctdb
)
188 struct ctdb_iface
*iface
;
190 while ((fgets(line
, sizeof(line
), stdin
) != NULL
) &&
194 char *tok
, *t
, *name
;
196 /* Get rid of pesky newline */
197 if ((t
= strchr(line
, '\n')) != NULL
) {
201 if (strcmp(line
, ":Name:LinkStatus:References:") == 0) {
206 //tok = strtok(line, ":"); /* Leading colon... */
207 tok
= strtok(line
, ":");
209 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line ignored \"%s\"\n", line
));
215 tok
= strtok(NULL
, ":");
217 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line ignored \"%s\"\n", line
));
220 link_state
= (uint16_t)strtoul(tok
, NULL
, 0);
223 tok
= strtok(NULL
, ":");
225 DEBUG(DEBUG_ERR
, (__location__
" WARNING, bad line ignored \"%s\"\n", line
));
228 references
= (uint32_t)strtoul(tok
, NULL
, 0);
230 iface
= talloc_zero(ctdb
, struct ctdb_iface
);
233 DEBUG(DEBUG_ERR
, ("OOM allocating iface\n"));
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?");
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",
279 struct ctdb_vnn_map {
285 static void ctdb_test_stubs_read_vnnmap(struct ctdb_context
*ctdb
)
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"));
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
) &&
305 /* Get rid of pesky newline */
306 if ((t
= strchr(line
, '\n')) != NULL
) {
310 n
= (uint32_t) strtol(line
, NULL
, 0);
313 if (ctdb
->vnn_map
->generation
== INVALID_GENERATION
) {
314 ctdb
->vnn_map
->generation
= n
;
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"));
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?");
337 #ifdef CTDB_TEST_OVERRIDE_MAIN
338 static void ctdb_test_stubs_print_vnnmap(struct ctdb_context
*ctdb
)
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
]);
351 static void ctdb_test_stubs_fake_setup(struct ctdb_context
*ctdb
)
355 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
358 /* Get rid of pesky newline */
359 if ((t
= strchr(line
, '\n')) != NULL
) {
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
);
370 printf("Unknown line %s\n", line
);
377 static bool current_node_is_connected (struct ctdb_context
*ctdb
)
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
)) {
394 /* Shouldn't really happen, so fag an error */
400 struct ctdb_context
*ctdb_cmdline_client_stub(struct tevent_context
*ev
,
401 struct timeval req_timeout
)
403 const char *t
= getenv("CTDB_DEBUGLEVEL");
410 ctdb_global
->ev
= ev
;
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
421 ctdb
= talloc_zero(NULL
, struct ctdb_context
);
423 ctdb_set_socketname(ctdb
, "fake");
425 ctdb_test_stubs_fake_setup(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
,
436 struct ctdb_node_map_old
**nodemap
)
438 assert_nodes_set(ctdb
);
440 if (!current_node_is_connected(ctdb
)) {
444 *nodemap
= ctdb_node_list_to_map(ctdb
->nodes
, ctdb
->num_nodes
,
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
)
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
);
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"));
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
);
492 ctdb_ctrl_getrecmode_stub(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
,
493 struct timeval timeout
, uint32_t destnode
,
496 *recmode
= ctdb
->recovery_mode
;
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
++;
517 ctdb_ctrl_getrecmaster_stub(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
,
518 struct timeval timeout
, uint32_t destnode
,
521 *recmaster
= ctdb
->recovery_master
;
527 ctdb_ctrl_getpnn_stub(struct ctdb_context
*ctdb
, struct timeval timeout
,
530 if (!current_node_is_connected(ctdb
)) {
534 if (destnode
== CTDB_CURRENT_NODE
) {
541 /* From ctdb_takeover.c */
542 int32_t ctdb_control_get_ifaces(struct ctdb_context
*ctdb
,
543 struct ctdb_req_control_old
*c
,
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 */
554 for (cur
=ctdb
->ifaces
;cur
;cur
=cur
->next
) {
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
);
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 */
571 ifaces
->ifaces
[i
].link_state
= cur
->link_up
;
572 ifaces
->ifaces
[i
].references
= cur
->references
;
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
;
586 ctdb_ctrl_get_ifaces_stub(struct ctdb_context
*ctdb
,
587 struct timeval timeout
, uint32_t destnode
,
589 struct ctdb_control_get_ifaces
**ifaces
)
594 if (!current_node_is_connected(ctdb
)) {
598 outdata
= talloc(mem_ctx
, TDB_DATA
);
600 ret
= ctdb_control_get_ifaces(ctdb
, NULL
, outdata
);
603 *ifaces
= (struct ctdb_control_get_ifaces
*)outdata
->dptr
;
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. */
613 srvid_handler_fn message_handler
;
614 void *message_private
;
615 } ctdb_message_list_fake
= {
617 .message_handler
= NULL
,
618 .message_private
= NULL
,
621 int ctdb_client_set_message_handler_stub(struct ctdb_context
*ctdb
,
623 srvid_handler_fn handler
,
626 ctdb_message_list_fake
.srvid
= srvid
;
627 ctdb_message_list_fake
.message_handler
= handler
;
628 ctdb_message_list_fake
.message_private
= private_data
;
633 int ctdb_client_remove_message_handler_stub(struct ctdb_context
*ctdb
,
637 ctdb_message_list_fake
.srvid
= 0;
638 ctdb_message_list_fake
.message_handler
= NULL
;
639 ctdb_message_list_fake
.message_private
= NULL
;
644 static void ctdb_fake_handler_pnn_reply(struct ctdb_context
*ctdb
,
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
,
654 ctdb_message_list_fake
.message_private
);
657 int ctdb_client_send_message_stub(struct ctdb_context
*ctdb
,
659 uint64_t srvid
, TDB_DATA data
)
661 struct srvid_reply_handler_data
*d
;
664 if (ctdb_message_list_fake
.message_handler
== NULL
) {
667 " no message handler registered for srvid %llu\n",
668 (unsigned long long)srvid
));
673 case CTDB_SRVID_TAKEOVER_RUN
:
674 /* Fake a single reply from recovery master */
676 ("Fake takeover run on recovery master %u\n",
677 ctdb
->recovery_master
));
678 ctdb_fake_handler_pnn_reply(ctdb
, ctdb
->recovery_master
);
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
) {
688 " srvid %llu must use pnn CTDB_BROADCAST_CONNECTED\n",
689 (unsigned long long)srvid
));
693 d
= (struct srvid_reply_handler_data
*)ctdb_message_list_fake
.message_private
;
696 (__location__
" No private data registered\n"));
699 if (d
->nodes
== NULL
) {
702 " No nodes to reply to in private data\n"));
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
]);
715 (__location__
" srvid %llu not implemented\n",
716 (unsigned long long)srvid
));
723 int ctdb_client_check_message_handlers_stub(struct ctdb_context
*ctdb
,
724 uint64_t *ids
, uint32_t num
,
727 DEBUG(DEBUG_ERR
, (__location__
" NOT IMPLEMENTED\n"));
731 int ctdb_ctrl_getcapabilities_stub(struct ctdb_context
*ctdb
,
732 struct timeval timeout
, uint32_t destnode
,
733 uint32_t *capabilities
)
737 assert_nodes_set(ctdb
);
739 if (ctdb
->nodes
[destnode
]->flags
& NODE_FLAGS_FAKE_TIMEOUT
) {
740 /* Placeholder for line#, instead of __location__ */
742 ("__LOCATION__ control timed out."
743 " reqid:1234567890 opcode:80 dstnode:%d\n", destnode
));
745 ("__LOCATION__ ctdb_control_recv failed\n"));
747 ("__LOCATION__ ctdb_ctrl_getcapabilities_recv failed\n"));
751 if (ctdb
->nodes
[destnode
]->flags
& NODE_FLAGS_DISCONNECTED
) {
753 ("ctdb_control error: 'ctdb_control to disconnected node\n"));
754 /* Placeholder for line#, instead of __location__ */
756 ("__LOCATION__ ctdb_ctrl_getcapabilities_recv failed\n"));
760 capp
= ctdb_get_node_capabilities(global_caps
, destnode
);
762 DEBUG(DEBUG_ERR
, ("__LOCATION__ invalid PNN\n"));
765 *capabilities
= *capp
;
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
));
776 /* This is to support testing ctdb xpnn */
778 bool ctdb_sys_have_ip_stub(ctdb_sock_addr
*addr
)
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
)) {
797 ctdb_client_async_control_stub(struct ctdb_context
*ctdb
,
798 enum ctdb_controls opcode
,
801 struct timeval timeout
,
802 bool dont_log_errors
,
804 client_async_callback client_callback
,
805 client_async_callback fail_callback
,
808 TALLOC_CTX
*tmp_ctx
= talloc_new(ctdb
);
812 for (i
= 0; i
< talloc_array_length(nodes
); i
++) {
813 uint32_t pnn
= nodes
[i
];
817 /* Not so async... but good enough for testing! */
819 case CTDB_CONTROL_RELOAD_NODES_FILE
:
820 res
= ctdb_ctrl_reload_nodes_file_stub(ctdb
, timeout
, pnn
);
822 case CTDB_CONTROL_RELOAD_PUBLIC_IPS
:
823 DEBUG(DEBUG_NOTICE
, ("Fake reload public IPs on node %u\n", pnn
));
826 case CTDB_CONTROL_GET_NODES_FILE
: {
827 struct ctdb_node_map_old
*nodemap
;
828 res
= ctdb_ctrl_getnodesfile_stub(ctdb
, timeout
, pnn
,
831 outdata
.dsize
= talloc_get_size(nodemap
);
832 outdata
.dptr
= (uint8_t *) nodemap
;
837 DEBUG(DEBUG_ERR
, (__location__
" Control not implemented %u\n",
839 talloc_free(tmp_ctx
);
844 if (client_callback
!= NULL
) {
845 client_callback(ctdb
, pnn
, res
, outdata
, callback_data
);
849 if (fail_callback
!= NULL
) {
850 fail_callback(ctdb
, pnn
, res
, outdata
, callback_data
);
855 talloc_free(tmp_ctx
);
859 struct ctdb_node_capabilities
*
860 ctdb_get_capabilities_stub(struct ctdb_context
*ctdb
,
862 struct timeval timeout
,
863 struct ctdb_node_map_old
*nodemap
)