4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/network.h"
23 #include "system/filesys.h"
24 #include "system/locale.h"
30 #include "lib/tdb_wrap/tdb_wrap.h"
31 #include "lib/util/dlinklist.h"
32 #include "lib/util/time.h"
33 #include "lib/util/debug.h"
34 #include "lib/util/samba_util.h"
36 #include "ctdb_private.h"
37 #include "ctdb_client.h"
39 #include "common/reqid.h"
40 #include "common/system.h"
41 #include "common/common.h"
42 #include "common/logging.h"
45 allocate a packet for use in client<->daemon communication
47 struct ctdb_req_header
*_ctdbd_allocate_pkt(struct ctdb_context
*ctdb
,
49 enum ctdb_operation operation
,
50 size_t length
, size_t slength
,
54 struct ctdb_req_header
*hdr
;
56 length
= MAX(length
, slength
);
57 size
= (length
+(CTDB_DS_ALIGNMENT
-1)) & ~(CTDB_DS_ALIGNMENT
-1);
59 hdr
= (struct ctdb_req_header
*)talloc_zero_size(mem_ctx
, size
);
61 DEBUG(DEBUG_ERR
,("Unable to allocate packet for operation %u of length %u\n",
62 operation
, (unsigned)length
));
65 talloc_set_name_const(hdr
, type
);
67 hdr
->operation
= operation
;
68 hdr
->ctdb_magic
= CTDB_MAGIC
;
69 hdr
->ctdb_version
= CTDB_PROTOCOL
;
70 hdr
->srcnode
= ctdb
->pnn
;
72 hdr
->generation
= ctdb
->vnn_map
->generation
;
79 local version of ctdb_call
81 int ctdb_call_local(struct ctdb_db_context
*ctdb_db
, struct ctdb_call
*call
,
82 struct ctdb_ltdb_header
*header
, TALLOC_CTX
*mem_ctx
,
83 TDB_DATA
*data
, bool updatetdb
)
85 struct ctdb_call_info
*c
;
86 struct ctdb_registered_call
*fn
;
87 struct ctdb_context
*ctdb
= ctdb_db
->ctdb
;
89 c
= talloc_zero(mem_ctx
, struct ctdb_call_info
);
90 CTDB_NO_MEMORY(ctdb
, c
);
93 c
->call_data
= &call
->call_data
;
94 c
->record_data
.dptr
= talloc_memdup(c
, data
->dptr
, data
->dsize
);
95 c
->record_data
.dsize
= data
->dsize
;
96 CTDB_NO_MEMORY(ctdb
, c
->record_data
.dptr
);
99 for (fn
=ctdb_db
->calls
;fn
;fn
=fn
->next
) {
100 if (fn
->id
== call
->call_id
) break;
103 ctdb_set_error(ctdb
, "Unknown call id %u\n", call
->call_id
);
108 if (fn
->fn(c
) != 0) {
109 ctdb_set_error(ctdb
, "ctdb_call %u failed\n", call
->call_id
);
114 /* we need to force the record to be written out if this was a remote access */
115 if (c
->new_data
== NULL
) {
116 c
->new_data
= &c
->record_data
;
119 if (c
->new_data
&& updatetdb
) {
120 /* XXX check that we always have the lock here? */
121 if (ctdb_ltdb_store(ctdb_db
, call
->key
, header
, *c
->new_data
) != 0) {
122 ctdb_set_error(ctdb
, "ctdb_call tdb_store failed\n");
129 call
->reply_data
= *c
->reply_data
;
131 talloc_steal(call
, call
->reply_data
.dptr
);
132 talloc_set_name_const(call
->reply_data
.dptr
, __location__
);
134 call
->reply_data
.dptr
= NULL
;
135 call
->reply_data
.dsize
= 0;
137 call
->status
= c
->status
;
146 queue a packet for sending from client to daemon
148 static int ctdb_client_queue_pkt(struct ctdb_context
*ctdb
, struct ctdb_req_header
*hdr
)
150 return ctdb_queue_send(ctdb
->daemon
.queue
, (uint8_t *)hdr
, hdr
->length
);
155 called when a CTDB_REPLY_CALL packet comes in in the client
157 This packet comes in response to a CTDB_REQ_CALL request packet. It
158 contains any reply data from the call
160 static void ctdb_client_reply_call(struct ctdb_context
*ctdb
, struct ctdb_req_header
*hdr
)
162 struct ctdb_reply_call_old
*c
= (struct ctdb_reply_call_old
*)hdr
;
163 struct ctdb_client_call_state
*state
;
165 state
= reqid_find(ctdb
->idr
, hdr
->reqid
, struct ctdb_client_call_state
);
167 DEBUG(DEBUG_ERR
,(__location__
" reqid %u not found\n", hdr
->reqid
));
171 if (hdr
->reqid
!= state
->reqid
) {
172 /* we found a record but it was the wrong one */
173 DEBUG(DEBUG_ERR
, ("Dropped client call reply with reqid:%u\n",hdr
->reqid
));
177 state
->call
->reply_data
.dptr
= c
->data
;
178 state
->call
->reply_data
.dsize
= c
->datalen
;
179 state
->call
->status
= c
->status
;
181 talloc_steal(state
, c
);
183 state
->state
= CTDB_CALL_DONE
;
185 if (state
->async
.fn
) {
186 state
->async
.fn(state
);
190 void ctdb_request_message(struct ctdb_context
*ctdb
,
191 struct ctdb_req_header
*hdr
)
193 struct ctdb_req_message_old
*c
= (struct ctdb_req_message_old
*)hdr
;
196 data
.dsize
= c
->datalen
;
197 data
.dptr
= talloc_memdup(c
, &c
->data
[0], c
->datalen
);
198 if (data
.dptr
== NULL
) {
199 DEBUG(DEBUG_ERR
, (__location__
" Memory allocation failure\n"));
203 srvid_dispatch(ctdb
->srv
, c
->srvid
, CTDB_SRVID_ALL
, data
);
206 static void ctdb_client_reply_control(struct ctdb_context
*ctdb
, struct ctdb_req_header
*hdr
);
209 this is called in the client, when data comes in from the daemon
211 void ctdb_client_read_cb(uint8_t *data
, size_t cnt
, void *args
)
213 struct ctdb_context
*ctdb
= talloc_get_type(args
, struct ctdb_context
);
214 struct ctdb_req_header
*hdr
= (struct ctdb_req_header
*)data
;
217 /* place the packet as a child of a tmp_ctx. We then use
218 talloc_free() below to free it. If any of the calls want
219 to keep it, then they will steal it somewhere else, and the
220 talloc_free() will be a no-op */
221 tmp_ctx
= talloc_new(ctdb
);
222 talloc_steal(tmp_ctx
, hdr
);
225 DEBUG(DEBUG_CRIT
,("Daemon has exited - shutting down client\n"));
229 if (cnt
< sizeof(*hdr
)) {
230 DEBUG(DEBUG_CRIT
,("Bad packet length %u in client\n", (unsigned)cnt
));
233 if (cnt
!= hdr
->length
) {
234 ctdb_set_error(ctdb
, "Bad header length %u expected %u in client\n",
235 (unsigned)hdr
->length
, (unsigned)cnt
);
239 if (hdr
->ctdb_magic
!= CTDB_MAGIC
) {
240 ctdb_set_error(ctdb
, "Non CTDB packet rejected in client\n");
244 if (hdr
->ctdb_version
!= CTDB_PROTOCOL
) {
245 ctdb_set_error(ctdb
, "Bad CTDB version 0x%x rejected in client\n", hdr
->ctdb_version
);
249 switch (hdr
->operation
) {
250 case CTDB_REPLY_CALL
:
251 ctdb_client_reply_call(ctdb
, hdr
);
254 case CTDB_REQ_MESSAGE
:
255 ctdb_request_message(ctdb
, hdr
);
258 case CTDB_REPLY_CONTROL
:
259 ctdb_client_reply_control(ctdb
, hdr
);
263 DEBUG(DEBUG_CRIT
,("bogus operation code:%u\n",hdr
->operation
));
267 talloc_free(tmp_ctx
);
271 connect to a unix domain socket
273 int ctdb_socket_connect(struct ctdb_context
*ctdb
)
275 struct sockaddr_un addr
;
278 memset(&addr
, 0, sizeof(addr
));
279 addr
.sun_family
= AF_UNIX
;
280 strncpy(addr
.sun_path
, ctdb
->daemon
.name
, sizeof(addr
.sun_path
)-1);
282 ctdb
->daemon
.sd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
283 if (ctdb
->daemon
.sd
== -1) {
284 DEBUG(DEBUG_ERR
,(__location__
" Failed to open client socket. Errno:%s(%d)\n", strerror(errno
), errno
));
288 if (connect(ctdb
->daemon
.sd
, (struct sockaddr
*)&addr
, sizeof(addr
)) == -1) {
291 "Failed to connect client socket to daemon (%s)\n",
293 close(ctdb
->daemon
.sd
);
294 ctdb
->daemon
.sd
= -1;
298 ret
= set_blocking(ctdb
->daemon
.sd
, false);
302 " failed to set socket non-blocking (%s)\n",
304 close(ctdb
->daemon
.sd
);
305 ctdb
->daemon
.sd
= -1;
309 set_close_on_exec(ctdb
->daemon
.sd
);
311 ctdb
->daemon
.queue
= ctdb_queue_setup(ctdb
, ctdb
, ctdb
->daemon
.sd
,
313 ctdb_client_read_cb
, ctdb
, "to-ctdbd");
318 struct ctdb_record_handle
{
319 struct ctdb_db_context
*ctdb_db
;
322 struct ctdb_ltdb_header header
;
327 make a recv call to the local ctdb daemon - called from client context
329 This is called when the program wants to wait for a ctdb_call to complete and get the
330 results. This call will block unless the call has already completed.
332 int ctdb_call_recv(struct ctdb_client_call_state
*state
, struct ctdb_call
*call
)
338 while (state
->state
< CTDB_CALL_DONE
) {
339 tevent_loop_once(state
->ctdb_db
->ctdb
->ev
);
341 if (state
->state
!= CTDB_CALL_DONE
) {
342 DEBUG(DEBUG_ERR
,(__location__
" ctdb_call_recv failed\n"));
347 if (state
->call
->reply_data
.dsize
) {
348 call
->reply_data
.dptr
= talloc_memdup(state
->ctdb_db
,
349 state
->call
->reply_data
.dptr
,
350 state
->call
->reply_data
.dsize
);
351 call
->reply_data
.dsize
= state
->call
->reply_data
.dsize
;
353 call
->reply_data
.dptr
= NULL
;
354 call
->reply_data
.dsize
= 0;
356 call
->status
= state
->call
->status
;
366 destroy a ctdb_call in client
368 static int ctdb_client_call_destructor(struct ctdb_client_call_state
*state
)
370 reqid_remove(state
->ctdb_db
->ctdb
->idr
, state
->reqid
);
375 construct an event driven local ctdb_call
377 this is used so that locally processed ctdb_call requests are processed
378 in an event driven manner
380 static struct ctdb_client_call_state
*ctdb_client_call_local_send(struct ctdb_db_context
*ctdb_db
,
381 struct ctdb_call
*call
,
382 struct ctdb_ltdb_header
*header
,
385 struct ctdb_client_call_state
*state
;
386 struct ctdb_context
*ctdb
= ctdb_db
->ctdb
;
389 state
= talloc_zero(ctdb_db
, struct ctdb_client_call_state
);
390 CTDB_NO_MEMORY_NULL(ctdb
, state
);
391 state
->call
= talloc_zero(state
, struct ctdb_call
);
392 CTDB_NO_MEMORY_NULL(ctdb
, state
->call
);
394 talloc_steal(state
, data
->dptr
);
396 state
->state
= CTDB_CALL_DONE
;
397 *(state
->call
) = *call
;
398 state
->ctdb_db
= ctdb_db
;
400 ret
= ctdb_call_local(ctdb_db
, state
->call
, header
, state
, data
, true);
402 DEBUG(DEBUG_DEBUG
,("ctdb_call_local() failed, ignoring return code %d\n", ret
));
409 make a ctdb call to the local daemon - async send. Called from client context.
411 This constructs a ctdb_call request and queues it for processing.
412 This call never blocks.
414 struct ctdb_client_call_state
*ctdb_call_send(struct ctdb_db_context
*ctdb_db
,
415 struct ctdb_call
*call
)
417 struct ctdb_client_call_state
*state
;
418 struct ctdb_context
*ctdb
= ctdb_db
->ctdb
;
419 struct ctdb_ltdb_header header
;
423 struct ctdb_req_call_old
*c
;
425 /* if the domain socket is not yet open, open it */
426 if (ctdb
->daemon
.sd
==-1) {
427 ctdb_socket_connect(ctdb
);
430 ret
= ctdb_ltdb_lock(ctdb_db
, call
->key
);
432 DEBUG(DEBUG_ERR
,(__location__
" Failed to get chainlock\n"));
436 ret
= ctdb_ltdb_fetch(ctdb_db
, call
->key
, &header
, ctdb_db
, &data
);
438 if ((call
->flags
& CTDB_IMMEDIATE_MIGRATION
) && (header
.flags
& CTDB_REC_RO_HAVE_DELEGATIONS
)) {
442 if (ret
== 0 && header
.dmaster
== ctdb
->pnn
) {
443 state
= ctdb_client_call_local_send(ctdb_db
, call
, &header
, &data
);
444 talloc_free(data
.dptr
);
445 ctdb_ltdb_unlock(ctdb_db
, call
->key
);
449 ctdb_ltdb_unlock(ctdb_db
, call
->key
);
450 talloc_free(data
.dptr
);
452 state
= talloc_zero(ctdb_db
, struct ctdb_client_call_state
);
454 DEBUG(DEBUG_ERR
, (__location__
" failed to allocate state\n"));
457 state
->call
= talloc_zero(state
, struct ctdb_call
);
458 if (state
->call
== NULL
) {
459 DEBUG(DEBUG_ERR
, (__location__
" failed to allocate state->call\n"));
463 len
= offsetof(struct ctdb_req_call_old
, data
) + call
->key
.dsize
+ call
->call_data
.dsize
;
464 c
= ctdbd_allocate_pkt(ctdb
, state
, CTDB_REQ_CALL
, len
, struct ctdb_req_call_old
);
466 DEBUG(DEBUG_ERR
, (__location__
" failed to allocate packet\n"));
470 state
->reqid
= reqid_new(ctdb
->idr
, state
);
471 state
->ctdb_db
= ctdb_db
;
472 talloc_set_destructor(state
, ctdb_client_call_destructor
);
474 c
->hdr
.reqid
= state
->reqid
;
475 c
->flags
= call
->flags
;
476 c
->db_id
= ctdb_db
->db_id
;
477 c
->callid
= call
->call_id
;
479 c
->keylen
= call
->key
.dsize
;
480 c
->calldatalen
= call
->call_data
.dsize
;
481 memcpy(&c
->data
[0], call
->key
.dptr
, call
->key
.dsize
);
482 memcpy(&c
->data
[call
->key
.dsize
],
483 call
->call_data
.dptr
, call
->call_data
.dsize
);
484 *(state
->call
) = *call
;
485 state
->call
->call_data
.dptr
= &c
->data
[call
->key
.dsize
];
486 state
->call
->key
.dptr
= &c
->data
[0];
488 state
->state
= CTDB_CALL_WAIT
;
491 ctdb_client_queue_pkt(ctdb
, &c
->hdr
);
498 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
500 int ctdb_call(struct ctdb_db_context
*ctdb_db
, struct ctdb_call
*call
)
502 struct ctdb_client_call_state
*state
;
504 state
= ctdb_call_send(ctdb_db
, call
);
505 return ctdb_call_recv(state
, call
);
510 tell the daemon what messaging srvid we will use, and register the message
511 handler function in the client
513 int ctdb_client_set_message_handler(struct ctdb_context
*ctdb
, uint64_t srvid
,
514 srvid_handler_fn handler
,
520 res
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, srvid
,
521 CTDB_CONTROL_REGISTER_SRVID
, 0,
522 tdb_null
, NULL
, NULL
, &status
, NULL
, NULL
);
523 if (res
!= 0 || status
!= 0) {
525 ("Failed to register srvid %llu\n",
526 (unsigned long long)srvid
));
530 /* also need to register the handler with our own ctdb structure */
531 return srvid_register(ctdb
->srv
, ctdb
, srvid
, handler
, private_data
);
535 tell the daemon we no longer want a srvid
537 int ctdb_client_remove_message_handler(struct ctdb_context
*ctdb
,
538 uint64_t srvid
, void *private_data
)
543 res
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, srvid
,
544 CTDB_CONTROL_DEREGISTER_SRVID
, 0,
545 tdb_null
, NULL
, NULL
, &status
, NULL
, NULL
);
546 if (res
!= 0 || status
!= 0) {
548 ("Failed to deregister srvid %llu\n",
549 (unsigned long long)srvid
));
553 /* also need to register the handler with our own ctdb structure */
554 srvid_deregister(ctdb
->srv
, srvid
, private_data
);
559 send a message - from client context
561 int ctdb_client_send_message(struct ctdb_context
*ctdb
, uint32_t pnn
,
562 uint64_t srvid
, TDB_DATA data
)
564 struct ctdb_req_message_old
*r
;
567 len
= offsetof(struct ctdb_req_message_old
, data
) + data
.dsize
;
568 r
= ctdbd_allocate_pkt(ctdb
, ctdb
, CTDB_REQ_MESSAGE
,
569 len
, struct ctdb_req_message_old
);
570 CTDB_NO_MEMORY(ctdb
, r
);
572 r
->hdr
.destnode
= pnn
;
574 r
->datalen
= data
.dsize
;
575 memcpy(&r
->data
[0], data
.dptr
, data
.dsize
);
577 res
= ctdb_client_queue_pkt(ctdb
, &r
->hdr
);
584 called when a control completes or timesout to invoke the callback
585 function the user provided
587 static void invoke_control_callback(struct tevent_context
*ev
,
588 struct tevent_timer
*te
,
589 struct timeval t
, void *private_data
)
591 struct ctdb_client_control_state
*state
;
592 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
595 state
= talloc_get_type(private_data
, struct ctdb_client_control_state
);
596 talloc_steal(tmp_ctx
, state
);
598 ret
= ctdb_control_recv(state
->ctdb
, state
, state
,
603 DEBUG(DEBUG_DEBUG
,("ctdb_control_recv() failed, ignoring return code %d\n", ret
));
606 talloc_free(tmp_ctx
);
610 called when a CTDB_REPLY_CONTROL packet comes in in the client
612 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
613 contains any reply data from the control
615 static void ctdb_client_reply_control(struct ctdb_context
*ctdb
,
616 struct ctdb_req_header
*hdr
)
618 struct ctdb_reply_control_old
*c
= (struct ctdb_reply_control_old
*)hdr
;
619 struct ctdb_client_control_state
*state
;
621 state
= reqid_find(ctdb
->idr
, hdr
->reqid
, struct ctdb_client_control_state
);
623 DEBUG(DEBUG_ERR
,(__location__
" reqid %u not found\n", hdr
->reqid
));
627 if (hdr
->reqid
!= state
->reqid
) {
628 /* we found a record but it was the wrong one */
629 DEBUG(DEBUG_ERR
, ("Dropped orphaned reply control with reqid:%u\n",hdr
->reqid
));
633 state
->outdata
.dptr
= c
->data
;
634 state
->outdata
.dsize
= c
->datalen
;
635 state
->status
= c
->status
;
637 state
->errormsg
= talloc_strndup(state
,
638 (char *)&c
->data
[c
->datalen
],
642 /* state->outdata now uses resources from c so we don't want c
643 to just dissappear from under us while state is still alive
645 talloc_steal(state
, c
);
647 state
->state
= CTDB_CONTROL_DONE
;
649 /* if we had a callback registered for this control, pull the response
650 and call the callback.
652 if (state
->async
.fn
) {
653 tevent_add_timer(ctdb
->ev
, state
, timeval_zero(),
654 invoke_control_callback
, state
);
660 destroy a ctdb_control in client
662 static int ctdb_client_control_destructor(struct ctdb_client_control_state
*state
)
664 reqid_remove(state
->ctdb
->idr
, state
->reqid
);
669 /* time out handler for ctdb_control */
670 static void control_timeout_func(struct tevent_context
*ev
,
671 struct tevent_timer
*te
,
672 struct timeval t
, void *private_data
)
674 struct ctdb_client_control_state
*state
= talloc_get_type(private_data
, struct ctdb_client_control_state
);
676 DEBUG(DEBUG_ERR
,(__location__
" control timed out. reqid:%u opcode:%u "
677 "dstnode:%u\n", state
->reqid
, state
->c
->opcode
,
678 state
->c
->hdr
.destnode
));
680 state
->state
= CTDB_CONTROL_TIMEOUT
;
682 /* if we had a callback registered for this control, pull the response
683 and call the callback.
685 if (state
->async
.fn
) {
686 tevent_add_timer(state
->ctdb
->ev
, state
, timeval_zero(),
687 invoke_control_callback
, state
);
691 /* async version of send control request */
692 struct ctdb_client_control_state
*ctdb_control_send(struct ctdb_context
*ctdb
,
693 uint32_t destnode
, uint64_t srvid
,
694 uint32_t opcode
, uint32_t flags
, TDB_DATA data
,
696 struct timeval
*timeout
,
699 struct ctdb_client_control_state
*state
;
701 struct ctdb_req_control_old
*c
;
708 /* if the domain socket is not yet open, open it */
709 if (ctdb
->daemon
.sd
==-1) {
710 ctdb_socket_connect(ctdb
);
713 state
= talloc_zero(mem_ctx
, struct ctdb_client_control_state
);
714 CTDB_NO_MEMORY_NULL(ctdb
, state
);
717 state
->reqid
= reqid_new(ctdb
->idr
, state
);
718 state
->state
= CTDB_CONTROL_WAIT
;
719 state
->errormsg
= NULL
;
721 talloc_set_destructor(state
, ctdb_client_control_destructor
);
723 len
= offsetof(struct ctdb_req_control_old
, data
) + data
.dsize
;
724 c
= ctdbd_allocate_pkt(ctdb
, state
, CTDB_REQ_CONTROL
,
725 len
, struct ctdb_req_control_old
);
727 CTDB_NO_MEMORY_NULL(ctdb
, c
);
728 c
->hdr
.reqid
= state
->reqid
;
729 c
->hdr
.destnode
= destnode
;
734 c
->datalen
= data
.dsize
;
736 memcpy(&c
->data
[0], data
.dptr
, data
.dsize
);
740 if (timeout
&& !timeval_is_zero(timeout
)) {
741 tevent_add_timer(ctdb
->ev
, state
, *timeout
,
742 control_timeout_func
, state
);
745 ret
= ctdb_client_queue_pkt(ctdb
, &(c
->hdr
));
751 if (flags
& CTDB_CTRL_FLAG_NOREPLY
) {
760 /* async version of receive control reply */
761 int ctdb_control_recv(struct ctdb_context
*ctdb
,
762 struct ctdb_client_control_state
*state
,
764 TDB_DATA
*outdata
, int32_t *status
, char **errormsg
)
768 if (status
!= NULL
) {
771 if (errormsg
!= NULL
) {
779 /* prevent double free of state */
780 tmp_ctx
= talloc_new(ctdb
);
781 talloc_steal(tmp_ctx
, state
);
783 /* loop one event at a time until we either timeout or the control
786 while (state
->state
== CTDB_CONTROL_WAIT
) {
787 tevent_loop_once(ctdb
->ev
);
790 if (state
->state
!= CTDB_CONTROL_DONE
) {
791 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control_recv failed\n"));
792 if (state
->async
.fn
) {
793 state
->async
.fn(state
);
795 talloc_free(tmp_ctx
);
799 if (state
->errormsg
) {
800 int s
= (state
->status
== 0 ? -1 : state
->status
);
801 DEBUG(DEBUG_ERR
,("ctdb_control error: '%s'\n", state
->errormsg
));
803 (*errormsg
) = talloc_move(mem_ctx
, &state
->errormsg
);
805 if (state
->async
.fn
) {
806 state
->async
.fn(state
);
808 talloc_free(tmp_ctx
);
813 *outdata
= state
->outdata
;
814 outdata
->dptr
= talloc_memdup(mem_ctx
, outdata
->dptr
, outdata
->dsize
);
818 *status
= state
->status
;
821 if (state
->async
.fn
) {
822 state
->async
.fn(state
);
825 talloc_free(tmp_ctx
);
832 send a ctdb control message
833 timeout specifies how long we should wait for a reply.
834 if timeout is NULL we wait indefinitely
836 int ctdb_control(struct ctdb_context
*ctdb
, uint32_t destnode
, uint64_t srvid
,
837 uint32_t opcode
, uint32_t flags
, TDB_DATA data
,
838 TALLOC_CTX
*mem_ctx
, TDB_DATA
*outdata
, int32_t *status
,
839 struct timeval
*timeout
,
842 struct ctdb_client_control_state
*state
;
844 state
= ctdb_control_send(ctdb
, destnode
, srvid
, opcode
,
845 flags
, data
, mem_ctx
,
848 /* FIXME: Error conditions in ctdb_control_send return NULL without
849 * setting errormsg. So, there is no way to distinguish between sucess
850 * and failure when CTDB_CTRL_FLAG_NOREPLY is set */
851 if (flags
& CTDB_CTRL_FLAG_NOREPLY
) {
852 if (status
!= NULL
) {
858 return ctdb_control_recv(ctdb
, state
, mem_ctx
, outdata
, status
,
863 get vnn map from a remote node
865 int ctdb_ctrl_getvnnmap(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, TALLOC_CTX
*mem_ctx
, struct ctdb_vnn_map
**vnnmap
)
870 struct ctdb_vnn_map_wire
*map
;
872 ret
= ctdb_control(ctdb
, destnode
, 0,
873 CTDB_CONTROL_GETVNNMAP
, 0, tdb_null
,
874 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
875 if (ret
!= 0 || res
!= 0) {
876 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getvnnmap failed\n"));
880 map
= (struct ctdb_vnn_map_wire
*)outdata
.dptr
;
881 if (outdata
.dsize
< offsetof(struct ctdb_vnn_map_wire
, map
) ||
882 outdata
.dsize
!= map
->size
*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire
, map
)) {
883 DEBUG(DEBUG_ERR
,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
887 (*vnnmap
) = talloc(mem_ctx
, struct ctdb_vnn_map
);
888 CTDB_NO_MEMORY(ctdb
, *vnnmap
);
889 (*vnnmap
)->generation
= map
->generation
;
890 (*vnnmap
)->size
= map
->size
;
891 (*vnnmap
)->map
= talloc_array(*vnnmap
, uint32_t, map
->size
);
893 CTDB_NO_MEMORY(ctdb
, (*vnnmap
)->map
);
894 memcpy((*vnnmap
)->map
, map
->map
, sizeof(uint32_t)*map
->size
);
895 talloc_free(outdata
.dptr
);
902 get the recovery mode of a remote node
904 struct ctdb_client_control_state
*
905 ctdb_ctrl_getrecmode_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
)
907 return ctdb_control_send(ctdb
, destnode
, 0,
908 CTDB_CONTROL_GET_RECMODE
, 0, tdb_null
,
909 mem_ctx
, &timeout
, NULL
);
912 int ctdb_ctrl_getrecmode_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, uint32_t *recmode
)
917 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, NULL
, &res
, NULL
);
919 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_getrecmode_recv failed\n"));
924 *recmode
= (uint32_t)res
;
930 int ctdb_ctrl_getrecmode(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, uint32_t *recmode
)
932 struct ctdb_client_control_state
*state
;
934 state
= ctdb_ctrl_getrecmode_send(ctdb
, mem_ctx
, timeout
, destnode
);
935 return ctdb_ctrl_getrecmode_recv(ctdb
, mem_ctx
, state
, recmode
);
942 set the recovery mode of a remote node
944 int ctdb_ctrl_setrecmode(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t recmode
)
950 data
.dsize
= sizeof(uint32_t);
951 data
.dptr
= (unsigned char *)&recmode
;
953 ret
= ctdb_control(ctdb
, destnode
, 0,
954 CTDB_CONTROL_SET_RECMODE
, 0, data
,
955 NULL
, NULL
, &res
, &timeout
, NULL
);
956 if (ret
!= 0 || res
!= 0) {
957 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setrecmode failed\n"));
967 get the recovery master of a remote node
969 struct ctdb_client_control_state
*
970 ctdb_ctrl_getrecmaster_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
,
971 struct timeval timeout
, uint32_t destnode
)
973 return ctdb_control_send(ctdb
, destnode
, 0,
974 CTDB_CONTROL_GET_RECMASTER
, 0, tdb_null
,
975 mem_ctx
, &timeout
, NULL
);
978 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, uint32_t *recmaster
)
983 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, NULL
, &res
, NULL
);
985 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_getrecmaster_recv failed\n"));
990 *recmaster
= (uint32_t)res
;
996 int ctdb_ctrl_getrecmaster(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, uint32_t *recmaster
)
998 struct ctdb_client_control_state
*state
;
1000 state
= ctdb_ctrl_getrecmaster_send(ctdb
, mem_ctx
, timeout
, destnode
);
1001 return ctdb_ctrl_getrecmaster_recv(ctdb
, mem_ctx
, state
, recmaster
);
1006 set the recovery master of a remote node
1008 int ctdb_ctrl_setrecmaster(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t recmaster
)
1015 data
.dsize
= sizeof(uint32_t);
1016 data
.dptr
= (unsigned char *)&recmaster
;
1018 ret
= ctdb_control(ctdb
, destnode
, 0,
1019 CTDB_CONTROL_SET_RECMASTER
, 0, data
,
1020 NULL
, NULL
, &res
, &timeout
, NULL
);
1021 if (ret
!= 0 || res
!= 0) {
1022 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setrecmaster failed\n"));
1031 get a list of databases off a remote node
1033 int ctdb_ctrl_getdbmap(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
,
1034 TALLOC_CTX
*mem_ctx
, struct ctdb_dbid_map_old
**dbmap
)
1040 ret
= ctdb_control(ctdb
, destnode
, 0,
1041 CTDB_CONTROL_GET_DBMAP
, 0, tdb_null
,
1042 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1043 if (ret
!= 0 || res
!= 0) {
1044 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getdbmap failed ret:%d res:%d\n", ret
, res
));
1048 *dbmap
= (struct ctdb_dbid_map_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
1049 talloc_free(outdata
.dptr
);
1055 get a list of nodes (vnn and flags ) from a remote node
1057 int ctdb_ctrl_getnodemap(struct ctdb_context
*ctdb
,
1058 struct timeval timeout
, uint32_t destnode
,
1059 TALLOC_CTX
*mem_ctx
, struct ctdb_node_map_old
**nodemap
)
1065 ret
= ctdb_control(ctdb
, destnode
, 0,
1066 CTDB_CONTROL_GET_NODEMAP
, 0, tdb_null
,
1067 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1068 if (ret
!= 0 || res
!= 0 || outdata
.dsize
== 0) {
1069 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getnodes failed ret:%d res:%d\n", ret
, res
));
1073 *nodemap
= (struct ctdb_node_map_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
1074 talloc_free(outdata
.dptr
);
1078 int ctdb_ctrl_get_runstate(struct ctdb_context
*ctdb
,
1079 struct timeval timeout
,
1087 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_RUNSTATE
, 0,
1088 tdb_null
, ctdb
, &outdata
, &res
, &timeout
, NULL
);
1089 if (ret
!= 0 || res
!= 0) {
1090 DEBUG(DEBUG_ERR
,("ctdb_control for get_runstate failed\n"));
1091 return ret
!= 0 ? ret
: res
;
1094 if (outdata
.dsize
!= sizeof(uint32_t)) {
1095 DEBUG(DEBUG_ERR
,("Invalid return data in get_runstate\n"));
1096 talloc_free(outdata
.dptr
);
1100 if (runstate
!= NULL
) {
1101 *runstate
= *(uint32_t *)outdata
.dptr
;
1103 talloc_free(outdata
.dptr
);
1109 find the real path to a ltdb
1111 int ctdb_ctrl_getdbpath(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t dbid
, TALLOC_CTX
*mem_ctx
,
1118 data
.dptr
= (uint8_t *)&dbid
;
1119 data
.dsize
= sizeof(dbid
);
1121 ret
= ctdb_control(ctdb
, destnode
, 0,
1122 CTDB_CONTROL_GETDBPATH
, 0, data
,
1123 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1124 if (ret
!= 0 || res
!= 0) {
1128 (*path
) = talloc_strndup(mem_ctx
, (const char *)data
.dptr
, data
.dsize
);
1129 if ((*path
) == NULL
) {
1133 talloc_free(data
.dptr
);
1139 find the name of a db
1141 int ctdb_ctrl_getdbname(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t dbid
, TALLOC_CTX
*mem_ctx
,
1148 data
.dptr
= (uint8_t *)&dbid
;
1149 data
.dsize
= sizeof(dbid
);
1151 ret
= ctdb_control(ctdb
, destnode
, 0,
1152 CTDB_CONTROL_GET_DBNAME
, 0, data
,
1153 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1154 if (ret
!= 0 || res
!= 0) {
1158 (*name
) = talloc_strndup(mem_ctx
, (const char *)data
.dptr
, data
.dsize
);
1159 if ((*name
) == NULL
) {
1163 talloc_free(data
.dptr
);
1171 int ctdb_ctrl_createdb(struct ctdb_context
*ctdb
, struct timeval timeout
,
1172 uint32_t destnode
, TALLOC_CTX
*mem_ctx
,
1173 const char *name
, uint8_t db_flags
, uint32_t *db_id
)
1180 data
.dptr
= discard_const(name
);
1181 data
.dsize
= strlen(name
)+1;
1183 if (db_flags
& CTDB_DB_FLAGS_PERSISTENT
) {
1184 opcode
= CTDB_CONTROL_DB_ATTACH_PERSISTENT
;
1185 } else if (db_flags
& CTDB_DB_FLAGS_REPLICATED
) {
1186 opcode
= CTDB_CONTROL_DB_ATTACH_REPLICATED
;
1188 opcode
= CTDB_CONTROL_DB_ATTACH
;
1191 ret
= ctdb_control(ctdb
, destnode
, 0, opcode
, 0, data
,
1192 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1194 if (ret
!= 0 || res
!= 0) {
1198 if (data
.dsize
!= sizeof(uint32_t)) {
1199 TALLOC_FREE(data
.dptr
);
1202 if (db_id
!= NULL
) {
1203 *db_id
= *(uint32_t *)data
.dptr
;
1205 talloc_free(data
.dptr
);
1211 get debug level on a node
1213 int ctdb_ctrl_get_debuglevel(struct ctdb_context
*ctdb
, uint32_t destnode
, int32_t *level
)
1219 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_DEBUG
, 0, tdb_null
,
1220 ctdb
, &data
, &res
, NULL
, NULL
);
1221 if (ret
!= 0 || res
!= 0) {
1224 if (data
.dsize
!= sizeof(int32_t)) {
1225 DEBUG(DEBUG_ERR
,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1226 (unsigned)data
.dsize
));
1229 *level
= *(int32_t *)data
.dptr
;
1230 talloc_free(data
.dptr
);
1237 int ctdb_ctrl_db_open_flags(struct ctdb_context
*ctdb
, uint32_t db_id
,
1240 TDB_DATA indata
, outdata
;
1244 indata
.dptr
= (uint8_t *)&db_id
;
1245 indata
.dsize
= sizeof(db_id
);
1247 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0,
1248 CTDB_CONTROL_DB_OPEN_FLAGS
, 0, indata
,
1249 ctdb
, &outdata
, &res
, NULL
, NULL
);
1250 if (ret
!= 0 || res
!= 0) {
1251 D_ERR("ctdb control for db open flags failed\n");
1255 if (outdata
.dsize
!= sizeof(int32_t)) {
1256 D_ERR(__location__
" expected %zi bytes, received %zi bytes\n",
1257 sizeof(int32_t), outdata
.dsize
);
1258 talloc_free(outdata
.dptr
);
1262 *tdb_flags
= *(int32_t *)outdata
.dptr
;
1263 talloc_free(outdata
.dptr
);
1268 attach to a specific database - client call
1270 struct ctdb_db_context
*ctdb_attach(struct ctdb_context
*ctdb
,
1271 struct timeval timeout
,
1275 struct ctdb_db_context
*ctdb_db
;
1279 ctdb_db
= ctdb_db_handle(ctdb
, name
);
1284 ctdb_db
= talloc_zero(ctdb
, struct ctdb_db_context
);
1285 CTDB_NO_MEMORY_NULL(ctdb
, ctdb_db
);
1287 ctdb_db
->ctdb
= ctdb
;
1288 ctdb_db
->db_name
= talloc_strdup(ctdb_db
, name
);
1289 CTDB_NO_MEMORY_NULL(ctdb
, ctdb_db
->db_name
);
1291 /* tell ctdb daemon to attach */
1292 ret
= ctdb_ctrl_createdb(ctdb
, timeout
, CTDB_CURRENT_NODE
,
1293 ctdb_db
, name
, db_flags
, &ctdb_db
->db_id
);
1295 DEBUG(DEBUG_ERR
,("Failed to attach to database '%s'\n", name
));
1296 talloc_free(ctdb_db
);
1300 ret
= ctdb_ctrl_getdbpath(ctdb
, timeout
, CTDB_CURRENT_NODE
, ctdb_db
->db_id
, ctdb_db
, &ctdb_db
->db_path
);
1302 DEBUG(DEBUG_ERR
,("Failed to get dbpath for database '%s'\n", name
));
1303 talloc_free(ctdb_db
);
1307 ret
= ctdb_ctrl_db_open_flags(ctdb
, ctdb_db
->db_id
, &tdb_flags
);
1309 D_ERR("Failed to get tdb_flags for database '%s'\n", name
);
1310 talloc_free(ctdb_db
);
1314 ctdb_db
->ltdb
= tdb_wrap_open(ctdb_db
, ctdb_db
->db_path
, 0, tdb_flags
,
1316 if (ctdb_db
->ltdb
== NULL
) {
1317 ctdb_set_error(ctdb
, "Failed to open tdb '%s'\n", ctdb_db
->db_path
);
1318 talloc_free(ctdb_db
);
1322 ctdb_db
->db_flags
= db_flags
;
1324 DLIST_ADD(ctdb
->db_list
, ctdb_db
);
1326 /* add well known functions */
1327 ctdb_set_call(ctdb_db
, ctdb_null_func
, CTDB_NULL_FUNC
);
1328 ctdb_set_call(ctdb_db
, ctdb_fetch_func
, CTDB_FETCH_FUNC
);
1329 ctdb_set_call(ctdb_db
, ctdb_fetch_with_header_func
, CTDB_FETCH_WITH_HEADER_FUNC
);
1335 setup a call for a database
1337 int ctdb_set_call(struct ctdb_db_context
*ctdb_db
, ctdb_fn_t fn
, uint32_t id
)
1339 struct ctdb_registered_call
*call
;
1341 /* register locally */
1342 call
= talloc(ctdb_db
, struct ctdb_registered_call
);
1346 DLIST_ADD(ctdb_db
->calls
, call
);
1350 /* Freeze all databases */
1351 int ctdb_ctrl_freeze(struct ctdb_context
*ctdb
, struct timeval timeout
,
1357 ret
= ctdb_control(ctdb
, destnode
, 0,
1358 CTDB_CONTROL_FREEZE
, 0, tdb_null
,
1359 NULL
, NULL
, &res
, &timeout
, NULL
);
1360 if (ret
!= 0 || res
!= 0) {
1361 DEBUG(DEBUG_ERR
, ("ctdb_ctrl_freeze_priority failed\n"));
1369 get pnn of a node, or -1
1371 int ctdb_ctrl_getpnn(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
)
1376 ret
= ctdb_control(ctdb
, destnode
, 0,
1377 CTDB_CONTROL_GET_PNN
, 0, tdb_null
,
1378 NULL
, NULL
, &res
, &timeout
, NULL
);
1380 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getpnn failed\n"));
1387 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context
*ctdb
,
1388 struct timeval timeout
, uint32_t destnode
,
1389 TALLOC_CTX
*mem_ctx
,
1391 struct ctdb_public_ip_list_old
**ips
)
1397 ret
= ctdb_control(ctdb
, destnode
, 0,
1398 CTDB_CONTROL_GET_PUBLIC_IPS
, flags
, tdb_null
,
1399 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1400 if (ret
!= 0 || res
!= 0) {
1401 DEBUG(DEBUG_ERR
,(__location__
1402 " ctdb_control for getpublicips failed ret:%d res:%d\n",
1407 *ips
= (struct ctdb_public_ip_list_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
1408 talloc_free(outdata
.dptr
);
1413 int ctdb_ctrl_get_public_ips(struct ctdb_context
*ctdb
,
1414 struct timeval timeout
, uint32_t destnode
,
1415 TALLOC_CTX
*mem_ctx
,
1416 struct ctdb_public_ip_list_old
**ips
)
1418 return ctdb_ctrl_get_public_ips_flags(ctdb
, timeout
,
1423 int ctdb_ctrl_get_ifaces(struct ctdb_context
*ctdb
,
1424 struct timeval timeout
, uint32_t destnode
,
1425 TALLOC_CTX
*mem_ctx
,
1426 struct ctdb_iface_list_old
**_ifaces
)
1431 struct ctdb_iface_list_old
*ifaces
;
1435 ret
= ctdb_control(ctdb
, destnode
, 0,
1436 CTDB_CONTROL_GET_IFACES
, 0, tdb_null
,
1437 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1438 if (ret
!= 0 || res
!= 0) {
1439 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
1440 "failed ret:%d res:%d\n",
1445 len
= offsetof(struct ctdb_iface_list_old
, ifaces
);
1446 if (len
> outdata
.dsize
) {
1447 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
1448 "returned invalid data with size %u > %u\n",
1449 (unsigned int)outdata
.dsize
,
1450 (unsigned int)len
));
1451 dump_data(DEBUG_DEBUG
, outdata
.dptr
, outdata
.dsize
);
1455 ifaces
= (struct ctdb_iface_list_old
*)outdata
.dptr
;
1456 len
+= ifaces
->num
*sizeof(struct ctdb_iface
);
1458 if (len
> outdata
.dsize
) {
1459 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
1460 "returned invalid data with size %u > %u\n",
1461 (unsigned int)outdata
.dsize
,
1462 (unsigned int)len
));
1463 dump_data(DEBUG_DEBUG
, outdata
.dptr
, outdata
.dsize
);
1467 /* make sure we null terminate the returned strings */
1468 for (i
=0; i
< ifaces
->num
; i
++) {
1469 ifaces
->ifaces
[i
].name
[CTDB_IFACE_SIZE
] = '\0';
1472 *_ifaces
= (struct ctdb_iface_list_old
*)talloc_memdup(mem_ctx
,
1475 talloc_free(outdata
.dptr
);
1476 if (*_ifaces
== NULL
) {
1477 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
1478 "talloc_memdup size %u failed\n",
1479 (unsigned int)outdata
.dsize
));
1487 set/clear the permanent disabled bit on a remote node
1489 int ctdb_ctrl_modflags(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
,
1490 uint32_t set
, uint32_t clear
)
1494 struct ctdb_node_map_old
*nodemap
=NULL
;
1495 struct ctdb_node_flag_change c
;
1496 TALLOC_CTX
*tmp_ctx
= talloc_new(ctdb
);
1501 /* find the recovery master */
1502 ret
= ctdb_ctrl_getrecmaster(ctdb
, tmp_ctx
, timeout
, CTDB_CURRENT_NODE
, &recmaster
);
1504 DEBUG(DEBUG_ERR
, (__location__
" Unable to get recmaster from local node\n"));
1505 talloc_free(tmp_ctx
);
1510 /* read the node flags from the recmaster */
1511 ret
= ctdb_ctrl_getnodemap(ctdb
, timeout
, recmaster
, tmp_ctx
, &nodemap
);
1513 DEBUG(DEBUG_ERR
, (__location__
" Unable to get nodemap from node %u\n", destnode
));
1514 talloc_free(tmp_ctx
);
1517 if (destnode
>= nodemap
->num
) {
1518 DEBUG(DEBUG_ERR
,(__location__
" Nodemap from recmaster does not contain node %d\n", destnode
));
1519 talloc_free(tmp_ctx
);
1524 c
.old_flags
= nodemap
->nodes
[destnode
].flags
;
1525 c
.new_flags
= c
.old_flags
;
1527 c
.new_flags
&= ~clear
;
1529 data
.dsize
= sizeof(c
);
1530 data
.dptr
= (unsigned char *)&c
;
1532 /* send the flags update to all connected nodes */
1533 nodes
= list_of_connected_nodes(ctdb
, nodemap
, tmp_ctx
, true);
1535 if (ctdb_client_async_control(ctdb
, CTDB_CONTROL_MODIFY_FLAGS
,
1537 timeout
, false, data
,
1540 DEBUG(DEBUG_ERR
, (__location__
" Unable to update nodeflags on remote nodes\n"));
1542 talloc_free(tmp_ctx
);
1546 talloc_free(tmp_ctx
);
1554 int ctdb_ctrl_get_all_tunables(struct ctdb_context
*ctdb
,
1555 struct timeval timeout
,
1557 struct ctdb_tunable_list
*tunables
)
1563 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_ALL_TUNABLES
, 0, tdb_null
, ctdb
,
1564 &outdata
, &res
, &timeout
, NULL
);
1565 if (ret
!= 0 || res
!= 0) {
1566 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get all tunables failed\n"));
1570 if (outdata
.dsize
!= sizeof(*tunables
)) {
1571 DEBUG(DEBUG_ERR
,(__location__
" bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
1572 (unsigned)outdata
.dsize
, (unsigned)sizeof(*tunables
)));
1576 *tunables
= *(struct ctdb_tunable_list
*)outdata
.dptr
;
1577 talloc_free(outdata
.dptr
);
1584 void ctdb_set_flags(struct ctdb_context
*ctdb
, unsigned flags
)
1586 ctdb
->flags
|= flags
;
1589 const char *ctdb_get_socketname(struct ctdb_context
*ctdb
)
1591 return ctdb
->daemon
.name
;
1595 return the pnn of this node
1597 uint32_t ctdb_get_pnn(struct ctdb_context
*ctdb
)
1603 callback for the async helpers used when sending the same control
1604 to multiple nodes in parallell.
1606 static void async_callback(struct ctdb_client_control_state
*state
)
1608 struct client_async_data
*data
= talloc_get_type(state
->async
.private_data
, struct client_async_data
);
1609 struct ctdb_context
*ctdb
= talloc_get_type(state
->ctdb
, struct ctdb_context
);
1613 uint32_t destnode
= state
->c
->hdr
.destnode
;
1616 outdata
.dptr
= NULL
;
1618 /* one more node has responded with recmode data */
1621 /* if we failed to push the db, then return an error and let
1622 the main loop try again.
1624 if (state
->state
!= CTDB_CONTROL_DONE
) {
1625 if ( !data
->dont_log_errors
) {
1626 DEBUG(DEBUG_ERR
,("Async operation failed with state %d, opcode:%u\n", state
->state
, data
->opcode
));
1629 if (state
->state
== CTDB_CONTROL_TIMEOUT
) {
1634 if (data
->fail_callback
) {
1635 data
->fail_callback(ctdb
, destnode
, res
, outdata
,
1636 data
->callback_data
);
1641 state
->async
.fn
= NULL
;
1643 ret
= ctdb_control_recv(ctdb
, state
, data
, &outdata
, &res
, NULL
);
1644 if ((ret
!= 0) || (res
!= 0)) {
1645 if ( !data
->dont_log_errors
) {
1646 DEBUG(DEBUG_ERR
,("Async operation failed with ret=%d res=%d opcode=%u\n", ret
, (int)res
, data
->opcode
));
1649 if (data
->fail_callback
) {
1650 data
->fail_callback(ctdb
, destnode
, res
, outdata
,
1651 data
->callback_data
);
1654 if ((ret
== 0) && (data
->callback
!= NULL
)) {
1655 data
->callback(ctdb
, destnode
, res
, outdata
,
1656 data
->callback_data
);
1661 void ctdb_client_async_add(struct client_async_data
*data
, struct ctdb_client_control_state
*state
)
1663 /* set up the callback functions */
1664 state
->async
.fn
= async_callback
;
1665 state
->async
.private_data
= data
;
1667 /* one more control to wait for to complete */
1672 /* wait for up to the maximum number of seconds allowed
1673 or until all nodes we expect a response from has replied
1675 int ctdb_client_async_wait(struct ctdb_context
*ctdb
, struct client_async_data
*data
)
1677 while (data
->count
> 0) {
1678 tevent_loop_once(ctdb
->ev
);
1680 if (data
->fail_count
!= 0) {
1681 if (!data
->dont_log_errors
) {
1682 DEBUG(DEBUG_ERR
,("Async wait failed - fail_count=%u\n",
1692 perform a simple control on the listed nodes
1693 The control cannot return data
1695 int ctdb_client_async_control(struct ctdb_context
*ctdb
,
1696 enum ctdb_controls opcode
,
1699 struct timeval timeout
,
1700 bool dont_log_errors
,
1702 client_async_callback client_callback
,
1703 client_async_callback fail_callback
,
1704 void *callback_data
)
1706 struct client_async_data
*async_data
;
1707 struct ctdb_client_control_state
*state
;
1710 async_data
= talloc_zero(ctdb
, struct client_async_data
);
1711 CTDB_NO_MEMORY_FATAL(ctdb
, async_data
);
1712 async_data
->dont_log_errors
= dont_log_errors
;
1713 async_data
->callback
= client_callback
;
1714 async_data
->fail_callback
= fail_callback
;
1715 async_data
->callback_data
= callback_data
;
1716 async_data
->opcode
= opcode
;
1718 num_nodes
= talloc_get_size(nodes
) / sizeof(uint32_t);
1720 /* loop over all nodes and send an async control to each of them */
1721 for (j
=0; j
<num_nodes
; j
++) {
1722 uint32_t pnn
= nodes
[j
];
1724 state
= ctdb_control_send(ctdb
, pnn
, srvid
, opcode
,
1725 0, data
, async_data
, &timeout
, NULL
);
1726 if (state
== NULL
) {
1727 DEBUG(DEBUG_ERR
,(__location__
" Failed to call async control %u\n", (unsigned)opcode
));
1728 talloc_free(async_data
);
1732 ctdb_client_async_add(async_data
, state
);
1735 if (ctdb_client_async_wait(ctdb
, async_data
) != 0) {
1736 talloc_free(async_data
);
1740 talloc_free(async_data
);
1744 uint32_t *list_of_vnnmap_nodes(struct ctdb_context
*ctdb
,
1745 struct ctdb_vnn_map
*vnn_map
,
1746 TALLOC_CTX
*mem_ctx
,
1749 int i
, j
, num_nodes
;
1752 for (i
=num_nodes
=0;i
<vnn_map
->size
;i
++) {
1753 if (vnn_map
->map
[i
] == ctdb
->pnn
&& !include_self
) {
1759 nodes
= talloc_array(mem_ctx
, uint32_t, num_nodes
);
1760 CTDB_NO_MEMORY_FATAL(ctdb
, nodes
);
1762 for (i
=j
=0;i
<vnn_map
->size
;i
++) {
1763 if (vnn_map
->map
[i
] == ctdb
->pnn
&& !include_self
) {
1766 nodes
[j
++] = vnn_map
->map
[i
];
1772 /* Get list of nodes not including those with flags specified by mask.
1773 * If exclude_pnn is not -1 then exclude that pnn from the list.
1775 static uint32_t *list_of_nodes(struct ctdb_context
*ctdb
,
1776 struct ctdb_node_map_old
*node_map
,
1777 TALLOC_CTX
*mem_ctx
,
1781 int i
, j
, num_nodes
;
1784 for (i
=num_nodes
=0;i
<node_map
->num
;i
++) {
1785 if (node_map
->nodes
[i
].flags
& mask
) {
1788 if (node_map
->nodes
[i
].pnn
== exclude_pnn
) {
1794 nodes
= talloc_array(mem_ctx
, uint32_t, num_nodes
);
1795 CTDB_NO_MEMORY_FATAL(ctdb
, nodes
);
1797 for (i
=j
=0;i
<node_map
->num
;i
++) {
1798 if (node_map
->nodes
[i
].flags
& mask
) {
1801 if (node_map
->nodes
[i
].pnn
== exclude_pnn
) {
1804 nodes
[j
++] = node_map
->nodes
[i
].pnn
;
1810 uint32_t *list_of_active_nodes(struct ctdb_context
*ctdb
,
1811 struct ctdb_node_map_old
*node_map
,
1812 TALLOC_CTX
*mem_ctx
,
1815 return list_of_nodes(ctdb
, node_map
, mem_ctx
, NODE_FLAGS_INACTIVE
,
1816 include_self
? -1 : ctdb
->pnn
);
1819 uint32_t *list_of_connected_nodes(struct ctdb_context
*ctdb
,
1820 struct ctdb_node_map_old
*node_map
,
1821 TALLOC_CTX
*mem_ctx
,
1824 return list_of_nodes(ctdb
, node_map
, mem_ctx
, NODE_FLAGS_DISCONNECTED
,
1825 include_self
? -1 : ctdb
->pnn
);
1829 get capabilities of a remote node
1831 struct ctdb_client_control_state
*
1832 ctdb_ctrl_getcapabilities_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
)
1834 return ctdb_control_send(ctdb
, destnode
, 0,
1835 CTDB_CONTROL_GET_CAPABILITIES
, 0, tdb_null
,
1836 mem_ctx
, &timeout
, NULL
);
1839 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, uint32_t *capabilities
)
1845 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, &outdata
, &res
, NULL
);
1846 if ( (ret
!= 0) || (res
!= 0) ) {
1847 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_getcapabilities_recv failed\n"));
1852 *capabilities
= *((uint32_t *)outdata
.dptr
);
1858 int ctdb_ctrl_getcapabilities(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t *capabilities
)
1860 struct ctdb_client_control_state
*state
;
1861 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
1864 state
= ctdb_ctrl_getcapabilities_send(ctdb
, tmp_ctx
, timeout
, destnode
);
1865 ret
= ctdb_ctrl_getcapabilities_recv(ctdb
, tmp_ctx
, state
, capabilities
);
1866 talloc_free(tmp_ctx
);
1870 static void get_capabilities_callback(struct ctdb_context
*ctdb
,
1871 uint32_t node_pnn
, int32_t res
,
1872 TDB_DATA outdata
, void *callback_data
)
1874 struct ctdb_node_capabilities
*caps
=
1875 talloc_get_type(callback_data
,
1876 struct ctdb_node_capabilities
);
1878 if ( (outdata
.dsize
!= sizeof(uint32_t)) || (outdata
.dptr
== NULL
) ) {
1879 DEBUG(DEBUG_ERR
, (__location__
" Invalid length/pointer for getcap callback : %u %p\n", (unsigned)outdata
.dsize
, outdata
.dptr
));
1883 if (node_pnn
>= talloc_array_length(caps
)) {
1885 (__location__
" unexpected PNN %u\n", node_pnn
));
1889 caps
[node_pnn
].retrieved
= true;
1890 caps
[node_pnn
].capabilities
= *((uint32_t *)outdata
.dptr
);
1893 struct ctdb_node_capabilities
*
1894 ctdb_get_capabilities(struct ctdb_context
*ctdb
,
1895 TALLOC_CTX
*mem_ctx
,
1896 struct timeval timeout
,
1897 struct ctdb_node_map_old
*nodemap
)
1901 struct ctdb_node_capabilities
*ret
;
1903 nodes
= list_of_active_nodes(ctdb
, nodemap
, mem_ctx
, true);
1905 ret
= talloc_array(mem_ctx
, struct ctdb_node_capabilities
,
1907 CTDB_NO_MEMORY_NULL(ctdb
, ret
);
1908 /* Prepopulate the expected PNNs */
1909 for (i
= 0; i
< talloc_array_length(ret
); i
++) {
1910 ret
[i
].retrieved
= false;
1913 res
= ctdb_client_async_control(ctdb
, CTDB_CONTROL_GET_CAPABILITIES
,
1916 get_capabilities_callback
, NULL
,
1920 (__location__
" Failed to read node capabilities.\n"));
1928 ctdb_get_node_capabilities(struct ctdb_node_capabilities
*caps
,
1931 if (pnn
< talloc_array_length(caps
) && caps
[pnn
].retrieved
) {
1932 return &caps
[pnn
].capabilities
;
1938 bool ctdb_node_has_capabilities(struct ctdb_node_capabilities
*caps
,
1940 uint32_t capabilities_required
)
1942 uint32_t *capp
= ctdb_get_node_capabilities(caps
, pnn
);
1943 return (capp
!= NULL
) &&
1944 ((*capp
& capabilities_required
) == capabilities_required
);
1948 recovery daemon ping to main daemon
1950 int ctdb_ctrl_recd_ping(struct ctdb_context
*ctdb
)
1955 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0, CTDB_CONTROL_RECD_PING
, 0, tdb_null
,
1956 ctdb
, NULL
, &res
, NULL
, NULL
);
1957 if (ret
!= 0 || res
!= 0) {
1958 DEBUG(DEBUG_ERR
,("Failed to send recd ping\n"));
1966 tell the main daemon how long it took to lock the reclock file
1968 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context
*ctdb
, struct timeval timeout
, double latency
)
1974 data
.dptr
= (uint8_t *)&latency
;
1975 data
.dsize
= sizeof(latency
);
1977 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY
, 0, data
,
1978 ctdb
, NULL
, &res
, NULL
, NULL
);
1979 if (ret
!= 0 || res
!= 0) {
1980 DEBUG(DEBUG_ERR
,("Failed to send recd reclock latency\n"));
1987 int ctdb_ctrl_set_ban(struct ctdb_context
*ctdb
, struct timeval timeout
,
1988 uint32_t destnode
, struct ctdb_ban_state
*bantime
)
1994 data
.dsize
= sizeof(*bantime
);
1995 data
.dptr
= (uint8_t *)bantime
;
1997 ret
= ctdb_control(ctdb
, destnode
, 0,
1998 CTDB_CONTROL_SET_BAN_STATE
, 0, data
,
1999 NULL
, NULL
, &res
, &timeout
, NULL
);
2000 if (ret
!= 0 || res
!= 0) {
2001 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for set ban state failed\n"));
2008 struct ctdb_client_control_state
*
2009 ctdb_ctrl_updaterecord_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, struct ctdb_db_context
*ctdb_db
, TDB_DATA key
, struct ctdb_ltdb_header
*header
, TDB_DATA data
)
2011 struct ctdb_client_control_state
*handle
;
2012 struct ctdb_marshall_buffer
*m
;
2013 struct ctdb_rec_data_old
*rec
;
2016 m
= talloc_zero(mem_ctx
, struct ctdb_marshall_buffer
);
2018 DEBUG(DEBUG_ERR
, ("Failed to allocate marshall buffer for update record\n"));
2022 m
->db_id
= ctdb_db
->db_id
;
2024 rec
= ctdb_marshall_record(m
, 0, key
, header
, data
);
2026 DEBUG(DEBUG_ERR
,("Failed to marshall record for update record\n"));
2030 m
= talloc_realloc_size(mem_ctx
, m
, rec
->length
+ offsetof(struct ctdb_marshall_buffer
, data
));
2032 DEBUG(DEBUG_CRIT
,(__location__
" Failed to expand recdata\n"));
2037 memcpy((uint8_t *)m
+ offsetof(struct ctdb_marshall_buffer
, data
), rec
, rec
->length
);
2040 outdata
.dptr
= (uint8_t *)m
;
2041 outdata
.dsize
= talloc_get_size(m
);
2043 handle
= ctdb_control_send(ctdb
, destnode
, 0,
2044 CTDB_CONTROL_UPDATE_RECORD
, 0, outdata
,
2045 mem_ctx
, &timeout
, NULL
);
2050 int ctdb_ctrl_updaterecord_recv(struct ctdb_context
*ctdb
, struct ctdb_client_control_state
*state
)
2055 ret
= ctdb_control_recv(ctdb
, state
, state
, NULL
, &res
, NULL
);
2056 if ( (ret
!= 0) || (res
!= 0) ){
2057 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_update_record_recv failed\n"));
2065 ctdb_ctrl_updaterecord(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, struct ctdb_db_context
*ctdb_db
, TDB_DATA key
, struct ctdb_ltdb_header
*header
, TDB_DATA data
)
2067 struct ctdb_client_control_state
*state
;
2069 state
= ctdb_ctrl_updaterecord_send(ctdb
, mem_ctx
, timeout
, destnode
, ctdb_db
, key
, header
, data
);
2070 return ctdb_ctrl_updaterecord_recv(ctdb
, state
);