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(ctdb
, 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
);
102 for (fn
=ctdb_db
->calls
;fn
;fn
=fn
->next
) {
103 if (fn
->id
== call
->call_id
) break;
106 ctdb_set_error(ctdb
, "Unknown call id %u\n", call
->call_id
);
111 if (fn
->fn(c
) != 0) {
112 ctdb_set_error(ctdb
, "ctdb_call %u failed\n", call
->call_id
);
117 /* we need to force the record to be written out if this was a remote access */
118 if (c
->new_data
== NULL
) {
119 c
->new_data
= &c
->record_data
;
122 if (c
->new_data
&& updatetdb
) {
123 /* XXX check that we always have the lock here? */
124 if (ctdb_ltdb_store(ctdb_db
, call
->key
, header
, *c
->new_data
) != 0) {
125 ctdb_set_error(ctdb
, "ctdb_call tdb_store failed\n");
132 call
->reply_data
= *c
->reply_data
;
134 talloc_steal(call
, call
->reply_data
.dptr
);
135 talloc_set_name_const(call
->reply_data
.dptr
, __location__
);
137 call
->reply_data
.dptr
= NULL
;
138 call
->reply_data
.dsize
= 0;
140 call
->status
= c
->status
;
149 queue a packet for sending from client to daemon
151 static int ctdb_client_queue_pkt(struct ctdb_context
*ctdb
, struct ctdb_req_header
*hdr
)
153 return ctdb_queue_send(ctdb
->daemon
.queue
, (uint8_t *)hdr
, hdr
->length
);
158 called when a CTDB_REPLY_CALL packet comes in in the client
160 This packet comes in response to a CTDB_REQ_CALL request packet. It
161 contains any reply data from the call
163 static void ctdb_client_reply_call(struct ctdb_context
*ctdb
, struct ctdb_req_header
*hdr
)
165 struct ctdb_reply_call_old
*c
= (struct ctdb_reply_call_old
*)hdr
;
166 struct ctdb_client_call_state
*state
;
168 state
= reqid_find(ctdb
->idr
, hdr
->reqid
, struct ctdb_client_call_state
);
170 DEBUG(DEBUG_ERR
,(__location__
" reqid %u not found\n", hdr
->reqid
));
174 if (hdr
->reqid
!= state
->reqid
) {
175 /* we found a record but it was the wrong one */
176 DEBUG(DEBUG_ERR
, ("Dropped client call reply with reqid:%u\n",hdr
->reqid
));
180 state
->call
->reply_data
.dptr
= c
->data
;
181 state
->call
->reply_data
.dsize
= c
->datalen
;
182 state
->call
->status
= c
->status
;
184 talloc_steal(state
, c
);
186 state
->state
= CTDB_CALL_DONE
;
188 if (state
->async
.fn
) {
189 state
->async
.fn(state
);
193 void ctdb_request_message(struct ctdb_context
*ctdb
,
194 struct ctdb_req_header
*hdr
)
196 struct ctdb_req_message_old
*c
= (struct ctdb_req_message_old
*)hdr
;
199 data
.dsize
= c
->datalen
;
200 data
.dptr
= talloc_memdup(c
, &c
->data
[0], c
->datalen
);
201 if (data
.dptr
== NULL
) {
202 DEBUG(DEBUG_ERR
, (__location__
" Memory allocation failure\n"));
206 srvid_dispatch(ctdb
->srv
, c
->srvid
, CTDB_SRVID_ALL
, data
);
209 static void ctdb_client_reply_control(struct ctdb_context
*ctdb
, struct ctdb_req_header
*hdr
);
212 this is called in the client, when data comes in from the daemon
214 void ctdb_client_read_cb(uint8_t *data
, size_t cnt
, void *args
)
216 struct ctdb_context
*ctdb
= talloc_get_type(args
, struct ctdb_context
);
217 struct ctdb_req_header
*hdr
= (struct ctdb_req_header
*)data
;
220 /* place the packet as a child of a tmp_ctx. We then use
221 talloc_free() below to free it. If any of the calls want
222 to keep it, then they will steal it somewhere else, and the
223 talloc_free() will be a no-op */
224 tmp_ctx
= talloc_new(ctdb
);
225 talloc_steal(tmp_ctx
, hdr
);
228 DEBUG(DEBUG_CRIT
,("Daemon has exited - shutting down client\n"));
232 if (cnt
< sizeof(*hdr
)) {
233 DEBUG(DEBUG_CRIT
,("Bad packet length %u in client\n", (unsigned)cnt
));
236 if (cnt
!= hdr
->length
) {
237 ctdb_set_error(ctdb
, "Bad header length %u expected %u in client\n",
238 (unsigned)hdr
->length
, (unsigned)cnt
);
242 if (hdr
->ctdb_magic
!= CTDB_MAGIC
) {
243 ctdb_set_error(ctdb
, "Non CTDB packet rejected in client\n");
247 if (hdr
->ctdb_version
!= CTDB_PROTOCOL
) {
248 ctdb_set_error(ctdb
, "Bad CTDB version 0x%x rejected in client\n", hdr
->ctdb_version
);
252 switch (hdr
->operation
) {
253 case CTDB_REPLY_CALL
:
254 ctdb_client_reply_call(ctdb
, hdr
);
257 case CTDB_REQ_MESSAGE
:
258 ctdb_request_message(ctdb
, hdr
);
261 case CTDB_REPLY_CONTROL
:
262 ctdb_client_reply_control(ctdb
, hdr
);
266 DEBUG(DEBUG_CRIT
,("bogus operation code:%u\n",hdr
->operation
));
270 talloc_free(tmp_ctx
);
274 connect to a unix domain socket
276 int ctdb_socket_connect(struct ctdb_context
*ctdb
)
278 struct sockaddr_un addr
;
281 memset(&addr
, 0, sizeof(addr
));
282 addr
.sun_family
= AF_UNIX
;
283 strncpy(addr
.sun_path
, ctdb
->daemon
.name
, sizeof(addr
.sun_path
)-1);
285 ctdb
->daemon
.sd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
286 if (ctdb
->daemon
.sd
== -1) {
287 DEBUG(DEBUG_ERR
,(__location__
" Failed to open client socket. Errno:%s(%d)\n", strerror(errno
), errno
));
291 if (connect(ctdb
->daemon
.sd
, (struct sockaddr
*)&addr
, sizeof(addr
)) == -1) {
294 "Failed to connect client socket to daemon (%s)\n",
296 close(ctdb
->daemon
.sd
);
297 ctdb
->daemon
.sd
= -1;
301 ret
= set_blocking(ctdb
->daemon
.sd
, false);
305 " failed to set socket non-blocking (%s)\n",
307 close(ctdb
->daemon
.sd
);
308 ctdb
->daemon
.sd
= -1;
312 set_close_on_exec(ctdb
->daemon
.sd
);
314 ctdb
->daemon
.queue
= ctdb_queue_setup(ctdb
, ctdb
, ctdb
->daemon
.sd
,
316 ctdb_client_read_cb
, ctdb
, "to-ctdbd");
321 struct ctdb_record_handle
{
322 struct ctdb_db_context
*ctdb_db
;
325 struct ctdb_ltdb_header header
;
330 make a recv call to the local ctdb daemon - called from client context
332 This is called when the program wants to wait for a ctdb_call to complete and get the
333 results. This call will block unless the call has already completed.
335 int ctdb_call_recv(struct ctdb_client_call_state
*state
, struct ctdb_call
*call
)
341 while (state
->state
< CTDB_CALL_DONE
) {
342 tevent_loop_once(state
->ctdb_db
->ctdb
->ev
);
344 if (state
->state
!= CTDB_CALL_DONE
) {
345 DEBUG(DEBUG_ERR
,(__location__
" ctdb_call_recv failed\n"));
350 if (state
->call
->reply_data
.dsize
) {
351 call
->reply_data
.dptr
= talloc_memdup(state
->ctdb_db
,
352 state
->call
->reply_data
.dptr
,
353 state
->call
->reply_data
.dsize
);
354 call
->reply_data
.dsize
= state
->call
->reply_data
.dsize
;
356 call
->reply_data
.dptr
= NULL
;
357 call
->reply_data
.dsize
= 0;
359 call
->status
= state
->call
->status
;
369 destroy a ctdb_call in client
371 static int ctdb_client_call_destructor(struct ctdb_client_call_state
*state
)
373 reqid_remove(state
->ctdb_db
->ctdb
->idr
, state
->reqid
);
378 construct an event driven local ctdb_call
380 this is used so that locally processed ctdb_call requests are processed
381 in an event driven manner
383 static struct ctdb_client_call_state
*ctdb_client_call_local_send(struct ctdb_db_context
*ctdb_db
,
384 struct ctdb_call
*call
,
385 struct ctdb_ltdb_header
*header
,
388 struct ctdb_client_call_state
*state
;
389 struct ctdb_context
*ctdb
= ctdb_db
->ctdb
;
392 state
= talloc_zero(ctdb_db
, struct ctdb_client_call_state
);
393 CTDB_NO_MEMORY_NULL(ctdb
, state
);
394 state
->call
= talloc_zero(state
, struct ctdb_call
);
395 CTDB_NO_MEMORY_NULL(ctdb
, state
->call
);
397 talloc_steal(state
, data
->dptr
);
399 state
->state
= CTDB_CALL_DONE
;
400 *(state
->call
) = *call
;
401 state
->ctdb_db
= ctdb_db
;
403 ret
= ctdb_call_local(ctdb_db
, state
->call
, header
, state
, data
, true);
405 DEBUG(DEBUG_DEBUG
,("ctdb_call_local() failed, ignoring return code %d\n", ret
));
412 make a ctdb call to the local daemon - async send. Called from client context.
414 This constructs a ctdb_call request and queues it for processing.
415 This call never blocks.
417 struct ctdb_client_call_state
*ctdb_call_send(struct ctdb_db_context
*ctdb_db
,
418 struct ctdb_call
*call
)
420 struct ctdb_client_call_state
*state
;
421 struct ctdb_context
*ctdb
= ctdb_db
->ctdb
;
422 struct ctdb_ltdb_header header
;
426 struct ctdb_req_call_old
*c
;
428 /* if the domain socket is not yet open, open it */
429 if (ctdb
->daemon
.sd
==-1) {
430 ctdb_socket_connect(ctdb
);
433 ret
= ctdb_ltdb_lock(ctdb_db
, call
->key
);
435 DEBUG(DEBUG_ERR
,(__location__
" Failed to get chainlock\n"));
439 ret
= ctdb_ltdb_fetch(ctdb_db
, call
->key
, &header
, ctdb_db
, &data
);
441 if ((call
->flags
& CTDB_IMMEDIATE_MIGRATION
) && (header
.flags
& CTDB_REC_RO_HAVE_DELEGATIONS
)) {
445 if (ret
== 0 && header
.dmaster
== ctdb
->pnn
) {
446 state
= ctdb_client_call_local_send(ctdb_db
, call
, &header
, &data
);
447 talloc_free(data
.dptr
);
448 ctdb_ltdb_unlock(ctdb_db
, call
->key
);
452 ctdb_ltdb_unlock(ctdb_db
, call
->key
);
453 talloc_free(data
.dptr
);
455 state
= talloc_zero(ctdb_db
, struct ctdb_client_call_state
);
457 DEBUG(DEBUG_ERR
, (__location__
" failed to allocate state\n"));
460 state
->call
= talloc_zero(state
, struct ctdb_call
);
461 if (state
->call
== NULL
) {
462 DEBUG(DEBUG_ERR
, (__location__
" failed to allocate state->call\n"));
466 len
= offsetof(struct ctdb_req_call_old
, data
) + call
->key
.dsize
+ call
->call_data
.dsize
;
467 c
= ctdbd_allocate_pkt(ctdb
, state
, CTDB_REQ_CALL
, len
, struct ctdb_req_call_old
);
469 DEBUG(DEBUG_ERR
, (__location__
" failed to allocate packet\n"));
473 state
->reqid
= reqid_new(ctdb
->idr
, state
);
474 state
->ctdb_db
= ctdb_db
;
475 talloc_set_destructor(state
, ctdb_client_call_destructor
);
477 c
->hdr
.reqid
= state
->reqid
;
478 c
->flags
= call
->flags
;
479 c
->db_id
= ctdb_db
->db_id
;
480 c
->callid
= call
->call_id
;
482 c
->keylen
= call
->key
.dsize
;
483 c
->calldatalen
= call
->call_data
.dsize
;
484 memcpy(&c
->data
[0], call
->key
.dptr
, call
->key
.dsize
);
485 memcpy(&c
->data
[call
->key
.dsize
],
486 call
->call_data
.dptr
, call
->call_data
.dsize
);
487 *(state
->call
) = *call
;
488 state
->call
->call_data
.dptr
= &c
->data
[call
->key
.dsize
];
489 state
->call
->key
.dptr
= &c
->data
[0];
491 state
->state
= CTDB_CALL_WAIT
;
494 ctdb_client_queue_pkt(ctdb
, &c
->hdr
);
501 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
503 int ctdb_call(struct ctdb_db_context
*ctdb_db
, struct ctdb_call
*call
)
505 struct ctdb_client_call_state
*state
;
507 state
= ctdb_call_send(ctdb_db
, call
);
508 return ctdb_call_recv(state
, call
);
513 tell the daemon what messaging srvid we will use, and register the message
514 handler function in the client
516 int ctdb_client_set_message_handler(struct ctdb_context
*ctdb
, uint64_t srvid
,
517 srvid_handler_fn handler
,
523 res
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, srvid
,
524 CTDB_CONTROL_REGISTER_SRVID
, 0,
525 tdb_null
, NULL
, NULL
, &status
, NULL
, NULL
);
526 if (res
!= 0 || status
!= 0) {
528 ("Failed to register srvid %llu\n",
529 (unsigned long long)srvid
));
533 /* also need to register the handler with our own ctdb structure */
534 return srvid_register(ctdb
->srv
, ctdb
, srvid
, handler
, private_data
);
538 tell the daemon we no longer want a srvid
540 int ctdb_client_remove_message_handler(struct ctdb_context
*ctdb
,
541 uint64_t srvid
, void *private_data
)
546 res
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, srvid
,
547 CTDB_CONTROL_DEREGISTER_SRVID
, 0,
548 tdb_null
, NULL
, NULL
, &status
, NULL
, NULL
);
549 if (res
!= 0 || status
!= 0) {
551 ("Failed to deregister srvid %llu\n",
552 (unsigned long long)srvid
));
556 /* also need to register the handler with our own ctdb structure */
557 srvid_deregister(ctdb
->srv
, srvid
, private_data
);
562 send a message - from client context
564 int ctdb_client_send_message(struct ctdb_context
*ctdb
, uint32_t pnn
,
565 uint64_t srvid
, TDB_DATA data
)
567 struct ctdb_req_message_old
*r
;
570 len
= offsetof(struct ctdb_req_message_old
, data
) + data
.dsize
;
571 r
= ctdbd_allocate_pkt(ctdb
, ctdb
, CTDB_REQ_MESSAGE
,
572 len
, struct ctdb_req_message_old
);
573 CTDB_NO_MEMORY(ctdb
, r
);
575 r
->hdr
.destnode
= pnn
;
577 r
->datalen
= data
.dsize
;
578 memcpy(&r
->data
[0], data
.dptr
, data
.dsize
);
580 res
= ctdb_client_queue_pkt(ctdb
, &r
->hdr
);
587 cancel a ctdb_fetch_lock operation, releasing the lock
589 static int fetch_lock_destructor(struct ctdb_record_handle
*h
)
591 ctdb_ltdb_unlock(h
->ctdb_db
, h
->key
);
596 force the migration of a record to this node
598 static int ctdb_client_force_migration(struct ctdb_db_context
*ctdb_db
, TDB_DATA key
)
600 struct ctdb_call call
;
602 call
.call_id
= CTDB_NULL_FUNC
;
604 call
.flags
= CTDB_IMMEDIATE_MIGRATION
;
605 return ctdb_call(ctdb_db
, &call
);
609 try to fetch a readonly copy of a record
612 ctdb_client_fetch_readonly(struct ctdb_db_context
*ctdb_db
, TDB_DATA key
, TALLOC_CTX
*mem_ctx
, struct ctdb_ltdb_header
**hdr
, TDB_DATA
*data
)
616 struct ctdb_call call
;
619 call
.call_id
= CTDB_FETCH_WITH_HEADER_FUNC
;
620 call
.call_data
.dptr
= NULL
;
621 call
.call_data
.dsize
= 0;
623 call
.flags
= CTDB_WANT_READONLY
;
624 ret
= ctdb_call(ctdb_db
, &call
);
629 if (call
.reply_data
.dsize
< sizeof(struct ctdb_ltdb_header
)) {
633 *hdr
= talloc_memdup(mem_ctx
, &call
.reply_data
.dptr
[0], sizeof(struct ctdb_ltdb_header
));
635 talloc_free(call
.reply_data
.dptr
);
639 data
->dsize
= call
.reply_data
.dsize
- sizeof(struct ctdb_ltdb_header
);
640 data
->dptr
= talloc_memdup(mem_ctx
, &call
.reply_data
.dptr
[sizeof(struct ctdb_ltdb_header
)], data
->dsize
);
641 if (data
->dptr
== NULL
) {
642 talloc_free(call
.reply_data
.dptr
);
651 get a lock on a record, and return the records data. Blocks until it gets the lock
653 struct ctdb_record_handle
*ctdb_fetch_lock(struct ctdb_db_context
*ctdb_db
, TALLOC_CTX
*mem_ctx
,
654 TDB_DATA key
, TDB_DATA
*data
)
657 struct ctdb_record_handle
*h
;
660 procedure is as follows:
662 1) get the chain lock.
663 2) check if we are dmaster
664 3) if we are the dmaster then return handle
665 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
667 5) when we get the reply, goto (1)
670 h
= talloc_zero(mem_ctx
, struct ctdb_record_handle
);
675 h
->ctdb_db
= ctdb_db
;
677 h
->key
.dptr
= talloc_memdup(h
, key
.dptr
, key
.dsize
);
678 if (h
->key
.dptr
== NULL
) {
684 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_lock: key=%*.*s\n", (int)key
.dsize
, (int)key
.dsize
,
685 (const char *)key
.dptr
));
688 /* step 1 - get the chain lock */
689 ret
= ctdb_ltdb_lock(ctdb_db
, key
);
691 DEBUG(DEBUG_ERR
, (__location__
" failed to lock ltdb record\n"));
696 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_lock: got chain lock\n"));
698 talloc_set_destructor(h
, fetch_lock_destructor
);
700 ret
= ctdb_ltdb_fetch(ctdb_db
, key
, &h
->header
, h
, data
);
702 /* when torturing, ensure we test the remote path */
703 if ((ctdb_db
->ctdb
->flags
& CTDB_FLAG_TORTURE
) &&
705 h
->header
.dmaster
= (uint32_t)-1;
709 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_lock: done local fetch\n"));
711 if (ret
!= 0 || h
->header
.dmaster
!= ctdb_db
->ctdb
->pnn
) {
712 ctdb_ltdb_unlock(ctdb_db
, key
);
713 ret
= ctdb_client_force_migration(ctdb_db
, key
);
715 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_lock: force_migration failed\n"));
722 /* if this is a request for read/write and we have delegations
723 we have to revoke all delegations first
725 if ((h
->header
.dmaster
== ctdb_db
->ctdb
->pnn
) &&
726 (h
->header
.flags
& CTDB_REC_RO_HAVE_DELEGATIONS
)) {
727 ctdb_ltdb_unlock(ctdb_db
, key
);
728 ret
= ctdb_client_force_migration(ctdb_db
, key
);
730 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_readonly_lock: force_migration failed\n"));
737 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_lock: we are dmaster - done\n"));
742 get a readonly lock on a record, and return the records data. Blocks until it gets the lock
744 struct ctdb_record_handle
*
745 ctdb_fetch_readonly_lock(
746 struct ctdb_db_context
*ctdb_db
, TALLOC_CTX
*mem_ctx
,
747 TDB_DATA key
, TDB_DATA
*data
,
751 struct ctdb_record_handle
*h
;
752 struct ctdb_ltdb_header
*roheader
= NULL
;
754 h
= talloc_zero(mem_ctx
, struct ctdb_record_handle
);
759 h
->ctdb_db
= ctdb_db
;
761 h
->key
.dptr
= talloc_memdup(h
, key
.dptr
, key
.dsize
);
762 if (h
->key
.dptr
== NULL
) {
773 talloc_free(roheader
);
776 talloc_free(data
->dptr
);
780 /* Lock the record/chain */
781 ret
= ctdb_ltdb_lock(ctdb_db
, key
);
783 DEBUG(DEBUG_ERR
, (__location__
" failed to lock ltdb record\n"));
788 talloc_set_destructor(h
, fetch_lock_destructor
);
790 /* Check if record exists yet in the TDB */
791 ret
= ctdb_ltdb_fetch_with_header(ctdb_db
, key
, &h
->header
, h
, data
);
793 ctdb_ltdb_unlock(ctdb_db
, key
);
794 ret
= ctdb_client_force_migration(ctdb_db
, key
);
796 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_readonly_lock: force_migration failed\n"));
803 /* if this is a request for read/write and we have delegations
804 we have to revoke all delegations first
807 && (h
->header
.dmaster
== ctdb_db
->ctdb
->pnn
)
808 && (h
->header
.flags
& CTDB_REC_RO_HAVE_DELEGATIONS
)) {
809 ctdb_ltdb_unlock(ctdb_db
, key
);
810 ret
= ctdb_client_force_migration(ctdb_db
, key
);
812 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_readonly_lock: force_migration failed\n"));
819 /* if we are dmaster, just return the handle */
820 if (h
->header
.dmaster
== ctdb_db
->ctdb
->pnn
) {
824 if (read_only
!= 0) {
825 TDB_DATA rodata
= {NULL
, 0};
827 if ((h
->header
.flags
& CTDB_REC_RO_HAVE_READONLY
)
828 || (h
->header
.flags
& CTDB_REC_RO_HAVE_DELEGATIONS
)) {
832 ctdb_ltdb_unlock(ctdb_db
, key
);
833 ret
= ctdb_client_fetch_readonly(ctdb_db
, key
, h
, &roheader
, &rodata
);
835 DEBUG(DEBUG_ERR
,("ctdb_fetch_readonly_lock: failed. force migration and try again\n"));
836 ret
= ctdb_client_force_migration(ctdb_db
, key
);
838 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_readonly_lock: force_migration failed\n"));
846 if (!(roheader
->flags
&CTDB_REC_RO_HAVE_READONLY
)) {
847 ret
= ctdb_client_force_migration(ctdb_db
, key
);
849 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_readonly_lock: force_migration failed\n"));
857 ret
= ctdb_ltdb_lock(ctdb_db
, key
);
859 DEBUG(DEBUG_ERR
, (__location__
" failed to lock ltdb record\n"));
864 ret
= ctdb_ltdb_fetch_with_header(ctdb_db
, key
, &h
->header
, h
, data
);
866 ctdb_ltdb_unlock(ctdb_db
, key
);
868 ret
= ctdb_client_force_migration(ctdb_db
, key
);
870 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_readonly_lock: force_migration failed\n"));
881 /* we are not dmaster and this was not a request for a readonly lock
882 * so unlock the record, migrate it and try again
884 ctdb_ltdb_unlock(ctdb_db
, key
);
885 ret
= ctdb_client_force_migration(ctdb_db
, key
);
887 DEBUG(DEBUG_DEBUG
,("ctdb_fetch_lock: force_migration failed\n"));
895 store some data to the record that was locked with ctdb_fetch_lock()
897 int ctdb_record_store(struct ctdb_record_handle
*h
, TDB_DATA data
)
899 if (! ctdb_db_volatile(h
->ctdb_db
)) {
901 ("ctdb_record_store prohibited for non-volatile dbs\n"));
905 return ctdb_ltdb_store(h
->ctdb_db
, h
->key
, &h
->header
, data
);
909 non-locking fetch of a record
911 int ctdb_fetch(struct ctdb_db_context
*ctdb_db
, TALLOC_CTX
*mem_ctx
,
912 TDB_DATA key
, TDB_DATA
*data
)
914 struct ctdb_call call
;
917 call
.call_id
= CTDB_FETCH_FUNC
;
918 call
.call_data
.dptr
= NULL
;
919 call
.call_data
.dsize
= 0;
922 ret
= ctdb_call(ctdb_db
, &call
);
925 *data
= call
.reply_data
;
926 talloc_steal(mem_ctx
, data
->dptr
);
935 called when a control completes or timesout to invoke the callback
936 function the user provided
938 static void invoke_control_callback(struct tevent_context
*ev
,
939 struct tevent_timer
*te
,
940 struct timeval t
, void *private_data
)
942 struct ctdb_client_control_state
*state
;
943 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
946 state
= talloc_get_type(private_data
, struct ctdb_client_control_state
);
947 talloc_steal(tmp_ctx
, state
);
949 ret
= ctdb_control_recv(state
->ctdb
, state
, state
,
954 DEBUG(DEBUG_DEBUG
,("ctdb_control_recv() failed, ignoring return code %d\n", ret
));
957 talloc_free(tmp_ctx
);
961 called when a CTDB_REPLY_CONTROL packet comes in in the client
963 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
964 contains any reply data from the control
966 static void ctdb_client_reply_control(struct ctdb_context
*ctdb
,
967 struct ctdb_req_header
*hdr
)
969 struct ctdb_reply_control_old
*c
= (struct ctdb_reply_control_old
*)hdr
;
970 struct ctdb_client_control_state
*state
;
972 state
= reqid_find(ctdb
->idr
, hdr
->reqid
, struct ctdb_client_control_state
);
974 DEBUG(DEBUG_ERR
,(__location__
" reqid %u not found\n", hdr
->reqid
));
978 if (hdr
->reqid
!= state
->reqid
) {
979 /* we found a record but it was the wrong one */
980 DEBUG(DEBUG_ERR
, ("Dropped orphaned reply control with reqid:%u\n",hdr
->reqid
));
984 state
->outdata
.dptr
= c
->data
;
985 state
->outdata
.dsize
= c
->datalen
;
986 state
->status
= c
->status
;
988 state
->errormsg
= talloc_strndup(state
,
989 (char *)&c
->data
[c
->datalen
],
993 /* state->outdata now uses resources from c so we don't want c
994 to just dissappear from under us while state is still alive
996 talloc_steal(state
, c
);
998 state
->state
= CTDB_CONTROL_DONE
;
1000 /* if we had a callback registered for this control, pull the response
1001 and call the callback.
1003 if (state
->async
.fn
) {
1004 tevent_add_timer(ctdb
->ev
, state
, timeval_zero(),
1005 invoke_control_callback
, state
);
1011 destroy a ctdb_control in client
1013 static int ctdb_client_control_destructor(struct ctdb_client_control_state
*state
)
1015 reqid_remove(state
->ctdb
->idr
, state
->reqid
);
1020 /* time out handler for ctdb_control */
1021 static void control_timeout_func(struct tevent_context
*ev
,
1022 struct tevent_timer
*te
,
1023 struct timeval t
, void *private_data
)
1025 struct ctdb_client_control_state
*state
= talloc_get_type(private_data
, struct ctdb_client_control_state
);
1027 DEBUG(DEBUG_ERR
,(__location__
" control timed out. reqid:%u opcode:%u "
1028 "dstnode:%u\n", state
->reqid
, state
->c
->opcode
,
1029 state
->c
->hdr
.destnode
));
1031 state
->state
= CTDB_CONTROL_TIMEOUT
;
1033 /* if we had a callback registered for this control, pull the response
1034 and call the callback.
1036 if (state
->async
.fn
) {
1037 tevent_add_timer(state
->ctdb
->ev
, state
, timeval_zero(),
1038 invoke_control_callback
, state
);
1042 /* async version of send control request */
1043 struct ctdb_client_control_state
*ctdb_control_send(struct ctdb_context
*ctdb
,
1044 uint32_t destnode
, uint64_t srvid
,
1045 uint32_t opcode
, uint32_t flags
, TDB_DATA data
,
1046 TALLOC_CTX
*mem_ctx
,
1047 struct timeval
*timeout
,
1050 struct ctdb_client_control_state
*state
;
1052 struct ctdb_req_control_old
*c
;
1059 /* if the domain socket is not yet open, open it */
1060 if (ctdb
->daemon
.sd
==-1) {
1061 ctdb_socket_connect(ctdb
);
1064 state
= talloc_zero(mem_ctx
, struct ctdb_client_control_state
);
1065 CTDB_NO_MEMORY_NULL(ctdb
, state
);
1068 state
->reqid
= reqid_new(ctdb
->idr
, state
);
1069 state
->state
= CTDB_CONTROL_WAIT
;
1070 state
->errormsg
= NULL
;
1072 talloc_set_destructor(state
, ctdb_client_control_destructor
);
1074 len
= offsetof(struct ctdb_req_control_old
, data
) + data
.dsize
;
1075 c
= ctdbd_allocate_pkt(ctdb
, state
, CTDB_REQ_CONTROL
,
1076 len
, struct ctdb_req_control_old
);
1078 CTDB_NO_MEMORY_NULL(ctdb
, c
);
1079 c
->hdr
.reqid
= state
->reqid
;
1080 c
->hdr
.destnode
= destnode
;
1085 c
->datalen
= data
.dsize
;
1087 memcpy(&c
->data
[0], data
.dptr
, data
.dsize
);
1091 if (timeout
&& !timeval_is_zero(timeout
)) {
1092 tevent_add_timer(ctdb
->ev
, state
, *timeout
,
1093 control_timeout_func
, state
);
1096 ret
= ctdb_client_queue_pkt(ctdb
, &(c
->hdr
));
1102 if (flags
& CTDB_CTRL_FLAG_NOREPLY
) {
1111 /* async version of receive control reply */
1112 int ctdb_control_recv(struct ctdb_context
*ctdb
,
1113 struct ctdb_client_control_state
*state
,
1114 TALLOC_CTX
*mem_ctx
,
1115 TDB_DATA
*outdata
, int32_t *status
, char **errormsg
)
1117 TALLOC_CTX
*tmp_ctx
;
1119 if (status
!= NULL
) {
1122 if (errormsg
!= NULL
) {
1126 if (state
== NULL
) {
1130 /* prevent double free of state */
1131 tmp_ctx
= talloc_new(ctdb
);
1132 talloc_steal(tmp_ctx
, state
);
1134 /* loop one event at a time until we either timeout or the control
1137 while (state
->state
== CTDB_CONTROL_WAIT
) {
1138 tevent_loop_once(ctdb
->ev
);
1141 if (state
->state
!= CTDB_CONTROL_DONE
) {
1142 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control_recv failed\n"));
1143 if (state
->async
.fn
) {
1144 state
->async
.fn(state
);
1146 talloc_free(tmp_ctx
);
1150 if (state
->errormsg
) {
1151 int s
= (state
->status
== 0 ? -1 : state
->status
);
1152 DEBUG(DEBUG_ERR
,("ctdb_control error: '%s'\n", state
->errormsg
));
1154 (*errormsg
) = talloc_move(mem_ctx
, &state
->errormsg
);
1156 if (state
->async
.fn
) {
1157 state
->async
.fn(state
);
1159 talloc_free(tmp_ctx
);
1164 *outdata
= state
->outdata
;
1165 outdata
->dptr
= talloc_memdup(mem_ctx
, outdata
->dptr
, outdata
->dsize
);
1169 *status
= state
->status
;
1172 if (state
->async
.fn
) {
1173 state
->async
.fn(state
);
1176 talloc_free(tmp_ctx
);
1183 send a ctdb control message
1184 timeout specifies how long we should wait for a reply.
1185 if timeout is NULL we wait indefinitely
1187 int ctdb_control(struct ctdb_context
*ctdb
, uint32_t destnode
, uint64_t srvid
,
1188 uint32_t opcode
, uint32_t flags
, TDB_DATA data
,
1189 TALLOC_CTX
*mem_ctx
, TDB_DATA
*outdata
, int32_t *status
,
1190 struct timeval
*timeout
,
1193 struct ctdb_client_control_state
*state
;
1195 state
= ctdb_control_send(ctdb
, destnode
, srvid
, opcode
,
1196 flags
, data
, mem_ctx
,
1199 /* FIXME: Error conditions in ctdb_control_send return NULL without
1200 * setting errormsg. So, there is no way to distinguish between sucess
1201 * and failure when CTDB_CTRL_FLAG_NOREPLY is set */
1202 if (flags
& CTDB_CTRL_FLAG_NOREPLY
) {
1203 if (status
!= NULL
) {
1209 return ctdb_control_recv(ctdb
, state
, mem_ctx
, outdata
, status
,
1217 a process exists call. Returns 0 if process exists, -1 otherwise
1219 int ctdb_ctrl_process_exists(struct ctdb_context
*ctdb
, uint32_t destnode
, pid_t pid
)
1225 data
.dptr
= (uint8_t*)&pid
;
1226 data
.dsize
= sizeof(pid
);
1228 ret
= ctdb_control(ctdb
, destnode
, 0,
1229 CTDB_CONTROL_PROCESS_EXISTS
, 0, data
,
1230 NULL
, NULL
, &status
, NULL
, NULL
);
1232 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for process_exists failed\n"));
1240 get remote statistics
1242 int ctdb_ctrl_statistics(struct ctdb_context
*ctdb
, uint32_t destnode
, struct ctdb_statistics
*status
)
1248 ret
= ctdb_control(ctdb
, destnode
, 0,
1249 CTDB_CONTROL_STATISTICS
, 0, tdb_null
,
1250 ctdb
, &data
, &res
, NULL
, NULL
);
1251 if (ret
!= 0 || res
!= 0) {
1252 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for statistics failed\n"));
1256 if (data
.dsize
!= sizeof(struct ctdb_statistics
)) {
1257 DEBUG(DEBUG_ERR
,(__location__
" Wrong statistics size %u - expected %u\n",
1258 (unsigned)data
.dsize
, (unsigned)sizeof(struct ctdb_statistics
)));
1262 *status
= *(struct ctdb_statistics
*)data
.dptr
;
1263 talloc_free(data
.dptr
);
1271 int ctdb_ctrl_dbstatistics(struct ctdb_context
*ctdb
, uint32_t destnode
, uint32_t dbid
,
1272 TALLOC_CTX
*mem_ctx
, struct ctdb_db_statistics_old
**dbstat
)
1275 TDB_DATA indata
, outdata
;
1277 struct ctdb_db_statistics_old
*wire
, *s
;
1281 indata
.dptr
= (uint8_t *)&dbid
;
1282 indata
.dsize
= sizeof(dbid
);
1284 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_DB_STATISTICS
,
1285 0, indata
, ctdb
, &outdata
, &res
, NULL
, NULL
);
1286 if (ret
!= 0 || res
!= 0) {
1287 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for dbstatistics failed\n"));
1291 if (outdata
.dsize
< offsetof(struct ctdb_db_statistics_old
, hot_keys_wire
)) {
1292 DEBUG(DEBUG_ERR
,(__location__
" Wrong dbstatistics size %zi - expected >= %lu\n",
1294 (long unsigned int)sizeof(struct ctdb_statistics
)));
1298 s
= talloc_zero(mem_ctx
, struct ctdb_db_statistics_old
);
1300 talloc_free(outdata
.dptr
);
1301 CTDB_NO_MEMORY(ctdb
, s
);
1304 wire
= (struct ctdb_db_statistics_old
*)outdata
.dptr
;
1305 memcpy(s
, wire
, offsetof(struct ctdb_db_statistics_old
, hot_keys_wire
));
1306 ptr
= &wire
->hot_keys_wire
[0];
1307 for (i
=0; i
<wire
->num_hot_keys
; i
++) {
1308 s
->hot_keys
[i
].key
.dptr
= talloc_size(mem_ctx
, s
->hot_keys
[i
].key
.dsize
);
1309 if (s
->hot_keys
[i
].key
.dptr
== NULL
) {
1310 talloc_free(outdata
.dptr
);
1311 CTDB_NO_MEMORY(ctdb
, s
->hot_keys
[i
].key
.dptr
);
1314 memcpy(s
->hot_keys
[i
].key
.dptr
, ptr
, s
->hot_keys
[i
].key
.dsize
);
1315 ptr
+= wire
->hot_keys
[i
].key
.dsize
;
1318 talloc_free(outdata
.dptr
);
1324 shutdown a remote ctdb node
1326 int ctdb_ctrl_shutdown(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
)
1328 struct ctdb_client_control_state
*state
;
1330 state
= ctdb_control_send(ctdb
, destnode
, 0,
1331 CTDB_CONTROL_SHUTDOWN
, 0, tdb_null
,
1332 NULL
, &timeout
, NULL
);
1333 if (state
== NULL
) {
1334 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for shutdown failed\n"));
1342 get vnn map from a remote node
1344 int ctdb_ctrl_getvnnmap(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, TALLOC_CTX
*mem_ctx
, struct ctdb_vnn_map
**vnnmap
)
1349 struct ctdb_vnn_map_wire
*map
;
1351 ret
= ctdb_control(ctdb
, destnode
, 0,
1352 CTDB_CONTROL_GETVNNMAP
, 0, tdb_null
,
1353 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1354 if (ret
!= 0 || res
!= 0) {
1355 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getvnnmap failed\n"));
1359 map
= (struct ctdb_vnn_map_wire
*)outdata
.dptr
;
1360 if (outdata
.dsize
< offsetof(struct ctdb_vnn_map_wire
, map
) ||
1361 outdata
.dsize
!= map
->size
*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire
, map
)) {
1362 DEBUG(DEBUG_ERR
,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1366 (*vnnmap
) = talloc(mem_ctx
, struct ctdb_vnn_map
);
1367 CTDB_NO_MEMORY(ctdb
, *vnnmap
);
1368 (*vnnmap
)->generation
= map
->generation
;
1369 (*vnnmap
)->size
= map
->size
;
1370 (*vnnmap
)->map
= talloc_array(*vnnmap
, uint32_t, map
->size
);
1372 CTDB_NO_MEMORY(ctdb
, (*vnnmap
)->map
);
1373 memcpy((*vnnmap
)->map
, map
->map
, sizeof(uint32_t)*map
->size
);
1374 talloc_free(outdata
.dptr
);
1381 get the recovery mode of a remote node
1383 struct ctdb_client_control_state
*
1384 ctdb_ctrl_getrecmode_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
)
1386 return ctdb_control_send(ctdb
, destnode
, 0,
1387 CTDB_CONTROL_GET_RECMODE
, 0, tdb_null
,
1388 mem_ctx
, &timeout
, NULL
);
1391 int ctdb_ctrl_getrecmode_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, uint32_t *recmode
)
1396 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, NULL
, &res
, NULL
);
1398 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_getrecmode_recv failed\n"));
1403 *recmode
= (uint32_t)res
;
1409 int ctdb_ctrl_getrecmode(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, uint32_t *recmode
)
1411 struct ctdb_client_control_state
*state
;
1413 state
= ctdb_ctrl_getrecmode_send(ctdb
, mem_ctx
, timeout
, destnode
);
1414 return ctdb_ctrl_getrecmode_recv(ctdb
, mem_ctx
, state
, recmode
);
1421 set the recovery mode of a remote node
1423 int ctdb_ctrl_setrecmode(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t recmode
)
1429 data
.dsize
= sizeof(uint32_t);
1430 data
.dptr
= (unsigned char *)&recmode
;
1432 ret
= ctdb_control(ctdb
, destnode
, 0,
1433 CTDB_CONTROL_SET_RECMODE
, 0, data
,
1434 NULL
, NULL
, &res
, &timeout
, NULL
);
1435 if (ret
!= 0 || res
!= 0) {
1436 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setrecmode failed\n"));
1446 get the recovery master of a remote node
1448 struct ctdb_client_control_state
*
1449 ctdb_ctrl_getrecmaster_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
,
1450 struct timeval timeout
, uint32_t destnode
)
1452 return ctdb_control_send(ctdb
, destnode
, 0,
1453 CTDB_CONTROL_GET_RECMASTER
, 0, tdb_null
,
1454 mem_ctx
, &timeout
, NULL
);
1457 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, uint32_t *recmaster
)
1462 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, NULL
, &res
, NULL
);
1464 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_getrecmaster_recv failed\n"));
1469 *recmaster
= (uint32_t)res
;
1475 int ctdb_ctrl_getrecmaster(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, uint32_t *recmaster
)
1477 struct ctdb_client_control_state
*state
;
1479 state
= ctdb_ctrl_getrecmaster_send(ctdb
, mem_ctx
, timeout
, destnode
);
1480 return ctdb_ctrl_getrecmaster_recv(ctdb
, mem_ctx
, state
, recmaster
);
1485 set the recovery master of a remote node
1487 int ctdb_ctrl_setrecmaster(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t recmaster
)
1494 data
.dsize
= sizeof(uint32_t);
1495 data
.dptr
= (unsigned char *)&recmaster
;
1497 ret
= ctdb_control(ctdb
, destnode
, 0,
1498 CTDB_CONTROL_SET_RECMASTER
, 0, data
,
1499 NULL
, NULL
, &res
, &timeout
, NULL
);
1500 if (ret
!= 0 || res
!= 0) {
1501 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setrecmaster failed\n"));
1510 get a list of databases off a remote node
1512 int ctdb_ctrl_getdbmap(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
,
1513 TALLOC_CTX
*mem_ctx
, struct ctdb_dbid_map_old
**dbmap
)
1519 ret
= ctdb_control(ctdb
, destnode
, 0,
1520 CTDB_CONTROL_GET_DBMAP
, 0, tdb_null
,
1521 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1522 if (ret
!= 0 || res
!= 0) {
1523 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getdbmap failed ret:%d res:%d\n", ret
, res
));
1527 *dbmap
= (struct ctdb_dbid_map_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
1528 talloc_free(outdata
.dptr
);
1534 get a list of nodes (vnn and flags ) from a remote node
1536 int ctdb_ctrl_getnodemap(struct ctdb_context
*ctdb
,
1537 struct timeval timeout
, uint32_t destnode
,
1538 TALLOC_CTX
*mem_ctx
, struct ctdb_node_map_old
**nodemap
)
1544 ret
= ctdb_control(ctdb
, destnode
, 0,
1545 CTDB_CONTROL_GET_NODEMAP
, 0, tdb_null
,
1546 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1547 if (ret
!= 0 || res
!= 0 || outdata
.dsize
== 0) {
1548 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getnodes failed ret:%d res:%d\n", ret
, res
));
1552 *nodemap
= (struct ctdb_node_map_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
1553 talloc_free(outdata
.dptr
);
1558 load nodes file on a remote node and return as a node map
1560 int ctdb_ctrl_getnodesfile(struct ctdb_context
*ctdb
,
1561 struct timeval timeout
, uint32_t destnode
,
1562 TALLOC_CTX
*mem_ctx
, struct ctdb_node_map_old
**nodemap
)
1568 ret
= ctdb_control(ctdb
, destnode
, 0,
1569 CTDB_CONTROL_GET_NODES_FILE
, 0, tdb_null
,
1570 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
1571 if (ret
!= 0 || res
!= 0 || outdata
.dsize
== 0) {
1572 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getnodes failed ret:%d res:%d\n", ret
, res
));
1576 *nodemap
= (struct ctdb_node_map_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
1577 talloc_free(outdata
.dptr
);
1583 drop the transport, reload the nodes file and restart the transport
1585 int ctdb_ctrl_reload_nodes_file(struct ctdb_context
*ctdb
,
1586 struct timeval timeout
, uint32_t destnode
)
1591 ret
= ctdb_control(ctdb
, destnode
, 0,
1592 CTDB_CONTROL_RELOAD_NODES_FILE
, 0, tdb_null
,
1593 NULL
, NULL
, &res
, &timeout
, NULL
);
1594 if (ret
!= 0 || res
!= 0) {
1595 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for reloadnodesfile failed\n"));
1604 set vnn map on a node
1606 int ctdb_ctrl_setvnnmap(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
,
1607 TALLOC_CTX
*mem_ctx
, struct ctdb_vnn_map
*vnnmap
)
1612 struct ctdb_vnn_map_wire
*map
;
1615 len
= offsetof(struct ctdb_vnn_map_wire
, map
) + sizeof(uint32_t)*vnnmap
->size
;
1616 map
= talloc_size(mem_ctx
, len
);
1617 CTDB_NO_MEMORY(ctdb
, map
);
1619 map
->generation
= vnnmap
->generation
;
1620 map
->size
= vnnmap
->size
;
1621 memcpy(map
->map
, vnnmap
->map
, sizeof(uint32_t)*map
->size
);
1624 data
.dptr
= (uint8_t *)map
;
1626 ret
= ctdb_control(ctdb
, destnode
, 0,
1627 CTDB_CONTROL_SETVNNMAP
, 0, data
,
1628 NULL
, NULL
, &res
, &timeout
, NULL
);
1629 if (ret
!= 0 || res
!= 0) {
1630 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setvnnmap failed\n"));
1641 async send for pull database
1643 struct ctdb_client_control_state
*ctdb_ctrl_pulldb_send(
1644 struct ctdb_context
*ctdb
, uint32_t destnode
, uint32_t dbid
,
1645 uint32_t lmaster
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
)
1648 struct ctdb_pulldb
*pull
;
1649 struct ctdb_client_control_state
*state
;
1651 pull
= talloc(mem_ctx
, struct ctdb_pulldb
);
1652 CTDB_NO_MEMORY_NULL(ctdb
, pull
);
1655 pull
->lmaster
= lmaster
;
1657 indata
.dsize
= sizeof(struct ctdb_pulldb
);
1658 indata
.dptr
= (unsigned char *)pull
;
1660 state
= ctdb_control_send(ctdb
, destnode
, 0,
1661 CTDB_CONTROL_PULL_DB
, 0, indata
,
1662 mem_ctx
, &timeout
, NULL
);
1669 async recv for pull database
1671 int ctdb_ctrl_pulldb_recv(
1672 struct ctdb_context
*ctdb
,
1673 TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
,
1679 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, outdata
, &res
, NULL
);
1680 if ( (ret
!= 0) || (res
!= 0) ){
1681 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_pulldb_recv failed\n"));
1689 pull all keys and records for a specific database on a node
1691 int ctdb_ctrl_pulldb(struct ctdb_context
*ctdb
, uint32_t destnode
,
1692 uint32_t dbid
, uint32_t lmaster
,
1693 TALLOC_CTX
*mem_ctx
, struct timeval timeout
,
1696 struct ctdb_client_control_state
*state
;
1698 state
= ctdb_ctrl_pulldb_send(ctdb
, destnode
, dbid
, lmaster
, mem_ctx
,
1701 return ctdb_ctrl_pulldb_recv(ctdb
, mem_ctx
, state
, outdata
);
1706 change dmaster for all keys in the database to the new value
1708 int ctdb_ctrl_setdmaster(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
,
1709 TALLOC_CTX
*mem_ctx
, uint32_t dbid
, uint32_t dmaster
)
1715 indata
.dsize
= 2*sizeof(uint32_t);
1716 indata
.dptr
= (unsigned char *)talloc_array(mem_ctx
, uint32_t, 2);
1718 ((uint32_t *)(&indata
.dptr
[0]))[0] = dbid
;
1719 ((uint32_t *)(&indata
.dptr
[0]))[1] = dmaster
;
1721 ret
= ctdb_control(ctdb
, destnode
, 0,
1722 CTDB_CONTROL_SET_DMASTER
, 0, indata
,
1723 NULL
, NULL
, &res
, &timeout
, NULL
);
1724 if (ret
!= 0 || res
!= 0) {
1725 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setdmaster failed\n"));
1733 ping a node, return number of clients connected
1735 int ctdb_ctrl_ping(struct ctdb_context
*ctdb
, uint32_t destnode
)
1740 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_PING
, 0,
1741 tdb_null
, NULL
, NULL
, &res
, NULL
, NULL
);
1748 int ctdb_ctrl_get_runstate(struct ctdb_context
*ctdb
,
1749 struct timeval timeout
,
1757 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_RUNSTATE
, 0,
1758 tdb_null
, ctdb
, &outdata
, &res
, &timeout
, NULL
);
1759 if (ret
!= 0 || res
!= 0) {
1760 DEBUG(DEBUG_ERR
,("ctdb_control for get_runstate failed\n"));
1761 return ret
!= 0 ? ret
: res
;
1764 if (outdata
.dsize
!= sizeof(uint32_t)) {
1765 DEBUG(DEBUG_ERR
,("Invalid return data in get_runstate\n"));
1766 talloc_free(outdata
.dptr
);
1770 if (runstate
!= NULL
) {
1771 *runstate
= *(uint32_t *)outdata
.dptr
;
1773 talloc_free(outdata
.dptr
);
1779 find the real path to a ltdb
1781 int ctdb_ctrl_getdbpath(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t dbid
, TALLOC_CTX
*mem_ctx
,
1788 data
.dptr
= (uint8_t *)&dbid
;
1789 data
.dsize
= sizeof(dbid
);
1791 ret
= ctdb_control(ctdb
, destnode
, 0,
1792 CTDB_CONTROL_GETDBPATH
, 0, data
,
1793 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1794 if (ret
!= 0 || res
!= 0) {
1798 (*path
) = talloc_strndup(mem_ctx
, (const char *)data
.dptr
, data
.dsize
);
1799 if ((*path
) == NULL
) {
1803 talloc_free(data
.dptr
);
1809 find the name of a db
1811 int ctdb_ctrl_getdbname(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t dbid
, TALLOC_CTX
*mem_ctx
,
1818 data
.dptr
= (uint8_t *)&dbid
;
1819 data
.dsize
= sizeof(dbid
);
1821 ret
= ctdb_control(ctdb
, destnode
, 0,
1822 CTDB_CONTROL_GET_DBNAME
, 0, data
,
1823 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1824 if (ret
!= 0 || res
!= 0) {
1828 (*name
) = talloc_strndup(mem_ctx
, (const char *)data
.dptr
, data
.dsize
);
1829 if ((*name
) == NULL
) {
1833 talloc_free(data
.dptr
);
1839 get the health status of a db
1841 int ctdb_ctrl_getdbhealth(struct ctdb_context
*ctdb
,
1842 struct timeval timeout
,
1844 uint32_t dbid
, TALLOC_CTX
*mem_ctx
,
1845 const char **reason
)
1851 data
.dptr
= (uint8_t *)&dbid
;
1852 data
.dsize
= sizeof(dbid
);
1854 ret
= ctdb_control(ctdb
, destnode
, 0,
1855 CTDB_CONTROL_DB_GET_HEALTH
, 0, data
,
1856 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1857 if (ret
!= 0 || res
!= 0) {
1861 if (data
.dsize
== 0) {
1866 (*reason
) = talloc_strndup(mem_ctx
, (const char *)data
.dptr
, data
.dsize
);
1867 if ((*reason
) == NULL
) {
1871 talloc_free(data
.dptr
);
1877 * get db sequence number
1879 int ctdb_ctrl_getdbseqnum(struct ctdb_context
*ctdb
, struct timeval timeout
,
1880 uint32_t destnode
, uint32_t dbid
, uint64_t *seqnum
)
1884 TDB_DATA data
, outdata
;
1885 uint8_t buf
[sizeof(uint64_t)] = { 0 };
1887 *(uint32_t *)buf
= dbid
;
1889 data
.dsize
= sizeof(uint64_t);
1891 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_DB_SEQNUM
,
1892 0, data
, ctdb
, &outdata
, &res
, &timeout
, NULL
);
1893 if (ret
!= 0 || res
!= 0) {
1894 DEBUG(DEBUG_ERR
,("ctdb_control for getdbesqnum failed\n"));
1898 if (outdata
.dsize
!= sizeof(uint64_t)) {
1899 DEBUG(DEBUG_ERR
,("Invalid return data in get_dbseqnum\n"));
1900 talloc_free(outdata
.dptr
);
1904 if (seqnum
!= NULL
) {
1905 *seqnum
= *(uint64_t *)outdata
.dptr
;
1907 talloc_free(outdata
.dptr
);
1915 int ctdb_ctrl_createdb(struct ctdb_context
*ctdb
, struct timeval timeout
,
1916 uint32_t destnode
, TALLOC_CTX
*mem_ctx
,
1917 const char *name
, uint8_t db_flags
, uint32_t *db_id
)
1924 data
.dptr
= discard_const(name
);
1925 data
.dsize
= strlen(name
)+1;
1927 if (db_flags
& CTDB_DB_FLAGS_PERSISTENT
) {
1928 opcode
= CTDB_CONTROL_DB_ATTACH_PERSISTENT
;
1929 } else if (db_flags
& CTDB_DB_FLAGS_REPLICATED
) {
1930 opcode
= CTDB_CONTROL_DB_ATTACH_REPLICATED
;
1932 opcode
= CTDB_CONTROL_DB_ATTACH
;
1935 ret
= ctdb_control(ctdb
, destnode
, 0, opcode
, 0, data
,
1936 mem_ctx
, &data
, &res
, &timeout
, NULL
);
1938 if (ret
!= 0 || res
!= 0) {
1942 if (data
.dsize
!= sizeof(uint32_t)) {
1943 TALLOC_FREE(data
.dptr
);
1946 if (db_id
!= NULL
) {
1947 *db_id
= *(uint32_t *)data
.dptr
;
1949 talloc_free(data
.dptr
);
1955 get debug level on a node
1957 int ctdb_ctrl_get_debuglevel(struct ctdb_context
*ctdb
, uint32_t destnode
, int32_t *level
)
1963 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_DEBUG
, 0, tdb_null
,
1964 ctdb
, &data
, &res
, NULL
, NULL
);
1965 if (ret
!= 0 || res
!= 0) {
1968 if (data
.dsize
!= sizeof(int32_t)) {
1969 DEBUG(DEBUG_ERR
,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1970 (unsigned)data
.dsize
));
1973 *level
= *(int32_t *)data
.dptr
;
1974 talloc_free(data
.dptr
);
1979 set debug level on a node
1981 int ctdb_ctrl_set_debuglevel(struct ctdb_context
*ctdb
, uint32_t destnode
, int32_t level
)
1987 data
.dptr
= (uint8_t *)&level
;
1988 data
.dsize
= sizeof(level
);
1990 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_SET_DEBUG
, 0, data
,
1991 NULL
, NULL
, &res
, NULL
, NULL
);
1992 if (ret
!= 0 || res
!= 0) {
2000 get a list of connected nodes
2002 uint32_t *ctdb_get_connected_nodes(struct ctdb_context
*ctdb
,
2003 struct timeval timeout
,
2004 TALLOC_CTX
*mem_ctx
,
2005 uint32_t *num_nodes
)
2007 struct ctdb_node_map_old
*map
=NULL
;
2013 ret
= ctdb_ctrl_getnodemap(ctdb
, timeout
, CTDB_CURRENT_NODE
, mem_ctx
, &map
);
2018 nodes
= talloc_array(mem_ctx
, uint32_t, map
->num
);
2019 if (nodes
== NULL
) {
2023 for (i
=0;i
<map
->num
;i
++) {
2024 if (!(map
->nodes
[i
].flags
& NODE_FLAGS_DISCONNECTED
)) {
2025 nodes
[*num_nodes
] = map
->nodes
[i
].pnn
;
2037 int ctdb_statistics_reset(struct ctdb_context
*ctdb
, uint32_t destnode
)
2042 ret
= ctdb_control(ctdb
, destnode
, 0,
2043 CTDB_CONTROL_STATISTICS_RESET
, 0, tdb_null
,
2044 NULL
, NULL
, &res
, NULL
, NULL
);
2045 if (ret
!= 0 || res
!= 0) {
2046 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for reset statistics failed\n"));
2055 int ctdb_ctrl_db_open_flags(struct ctdb_context
*ctdb
, uint32_t db_id
,
2058 TDB_DATA indata
, outdata
;
2062 indata
.dptr
= (uint8_t *)&db_id
;
2063 indata
.dsize
= sizeof(db_id
);
2065 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0,
2066 CTDB_CONTROL_DB_OPEN_FLAGS
, 0, indata
,
2067 ctdb
, &outdata
, &res
, NULL
, NULL
);
2068 if (ret
!= 0 || res
!= 0) {
2069 D_ERR("ctdb control for db open flags failed\n");
2073 if (outdata
.dsize
!= sizeof(int32_t)) {
2074 D_ERR(__location__
" expected %zi bytes, received %zi bytes\n",
2075 sizeof(int32_t), outdata
.dsize
);
2076 talloc_free(outdata
.dptr
);
2080 *tdb_flags
= *(int32_t *)outdata
.dptr
;
2081 talloc_free(outdata
.dptr
);
2086 attach to a specific database - client call
2088 struct ctdb_db_context
*ctdb_attach(struct ctdb_context
*ctdb
,
2089 struct timeval timeout
,
2093 struct ctdb_db_context
*ctdb_db
;
2097 ctdb_db
= ctdb_db_handle(ctdb
, name
);
2102 ctdb_db
= talloc_zero(ctdb
, struct ctdb_db_context
);
2103 CTDB_NO_MEMORY_NULL(ctdb
, ctdb_db
);
2105 ctdb_db
->ctdb
= ctdb
;
2106 ctdb_db
->db_name
= talloc_strdup(ctdb_db
, name
);
2107 CTDB_NO_MEMORY_NULL(ctdb
, ctdb_db
->db_name
);
2109 /* tell ctdb daemon to attach */
2110 ret
= ctdb_ctrl_createdb(ctdb
, timeout
, CTDB_CURRENT_NODE
,
2111 ctdb_db
, name
, db_flags
, &ctdb_db
->db_id
);
2113 DEBUG(DEBUG_ERR
,("Failed to attach to database '%s'\n", name
));
2114 talloc_free(ctdb_db
);
2118 ret
= ctdb_ctrl_getdbpath(ctdb
, timeout
, CTDB_CURRENT_NODE
, ctdb_db
->db_id
, ctdb_db
, &ctdb_db
->db_path
);
2120 DEBUG(DEBUG_ERR
,("Failed to get dbpath for database '%s'\n", name
));
2121 talloc_free(ctdb_db
);
2125 ret
= ctdb_ctrl_db_open_flags(ctdb
, ctdb_db
->db_id
, &tdb_flags
);
2127 D_ERR("Failed to get tdb_flags for database '%s'\n", name
);
2128 talloc_free(ctdb_db
);
2132 ctdb_db
->ltdb
= tdb_wrap_open(ctdb_db
, ctdb_db
->db_path
, 0, tdb_flags
,
2134 if (ctdb_db
->ltdb
== NULL
) {
2135 ctdb_set_error(ctdb
, "Failed to open tdb '%s'\n", ctdb_db
->db_path
);
2136 talloc_free(ctdb_db
);
2140 ctdb_db
->db_flags
= db_flags
;
2142 DLIST_ADD(ctdb
->db_list
, ctdb_db
);
2144 /* add well known functions */
2145 ctdb_set_call(ctdb_db
, ctdb_null_func
, CTDB_NULL_FUNC
);
2146 ctdb_set_call(ctdb_db
, ctdb_fetch_func
, CTDB_FETCH_FUNC
);
2147 ctdb_set_call(ctdb_db
, ctdb_fetch_with_header_func
, CTDB_FETCH_WITH_HEADER_FUNC
);
2153 * detach from a specific database - client call
2155 int ctdb_detach(struct ctdb_context
*ctdb
, uint32_t db_id
)
2161 data
.dsize
= sizeof(db_id
);
2162 data
.dptr
= (uint8_t *)&db_id
;
2164 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0, CTDB_CONTROL_DB_DETACH
,
2165 0, data
, NULL
, NULL
, &status
, NULL
, NULL
);
2166 if (ret
!= 0 || status
!= 0) {
2173 setup a call for a database
2175 int ctdb_set_call(struct ctdb_db_context
*ctdb_db
, ctdb_fn_t fn
, uint32_t id
)
2177 struct ctdb_registered_call
*call
;
2179 /* register locally */
2180 call
= talloc(ctdb_db
, struct ctdb_registered_call
);
2184 DLIST_ADD(ctdb_db
->calls
, call
);
2189 struct traverse_state
{
2192 ctdb_traverse_func fn
;
2194 bool listemptyrecords
;
2198 called on each key during a ctdb_traverse
2200 static void traverse_handler(uint64_t srvid
, TDB_DATA data
, void *p
)
2202 struct traverse_state
*state
= (struct traverse_state
*)p
;
2203 struct ctdb_rec_data_old
*d
= (struct ctdb_rec_data_old
*)data
.dptr
;
2206 if (data
.dsize
< sizeof(uint32_t) || d
->length
!= data
.dsize
) {
2207 DEBUG(DEBUG_ERR
, ("Bad data size %u in traverse_handler\n",
2208 (unsigned)data
.dsize
));
2213 key
.dsize
= d
->keylen
;
2214 key
.dptr
= &d
->data
[0];
2215 data
.dsize
= d
->datalen
;
2216 data
.dptr
= &d
->data
[d
->keylen
];
2218 if (key
.dsize
== 0 && data
.dsize
== 0) {
2219 /* end of traverse */
2224 if (!state
->listemptyrecords
&&
2225 data
.dsize
== sizeof(struct ctdb_ltdb_header
))
2227 /* empty records are deleted records in ctdb */
2231 if (state
->fn(key
, data
, state
->private_data
) != 0) {
2239 * start a cluster wide traverse, calling the supplied fn on each record
2240 * return the number of records traversed, or -1 on error
2242 * Extendet variant with a flag to signal whether empty records should
2245 static int ctdb_traverse_ext(struct ctdb_db_context
*ctdb_db
,
2246 ctdb_traverse_func fn
,
2247 bool withemptyrecords
,
2251 struct ctdb_traverse_start_ext t
;
2254 uint64_t srvid
= (getpid() | 0xFLL
<<60);
2255 struct traverse_state state
;
2259 state
.private_data
= private_data
;
2261 state
.listemptyrecords
= withemptyrecords
;
2263 ret
= ctdb_client_set_message_handler(ctdb_db
->ctdb
, srvid
, traverse_handler
, &state
);
2265 DEBUG(DEBUG_ERR
,("Failed to setup traverse handler\n"));
2269 t
.db_id
= ctdb_db
->db_id
;
2272 t
.withemptyrecords
= withemptyrecords
;
2274 data
.dptr
= (uint8_t *)&t
;
2275 data
.dsize
= sizeof(t
);
2277 ret
= ctdb_control(ctdb_db
->ctdb
, CTDB_CURRENT_NODE
, 0, CTDB_CONTROL_TRAVERSE_START_EXT
, 0,
2278 data
, NULL
, NULL
, &status
, NULL
, NULL
);
2279 if (ret
!= 0 || status
!= 0) {
2280 DEBUG(DEBUG_ERR
,("ctdb_traverse_all failed\n"));
2281 ctdb_client_remove_message_handler(ctdb_db
->ctdb
, srvid
, &state
);
2285 while (!state
.done
) {
2286 tevent_loop_once(ctdb_db
->ctdb
->ev
);
2289 ret
= ctdb_client_remove_message_handler(ctdb_db
->ctdb
, srvid
, &state
);
2291 DEBUG(DEBUG_ERR
,("Failed to remove ctdb_traverse handler\n"));
2299 * start a cluster wide traverse, calling the supplied fn on each record
2300 * return the number of records traversed, or -1 on error
2302 * Standard version which does not list the empty records:
2303 * These are considered deleted.
2305 int ctdb_traverse(struct ctdb_db_context
*ctdb_db
, ctdb_traverse_func fn
, void *private_data
)
2307 return ctdb_traverse_ext(ctdb_db
, fn
, false, private_data
);
2310 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
2312 called on each key during a catdb
2314 int ctdb_dumpdb_record(TDB_DATA key
, TDB_DATA data
, void *p
)
2317 struct ctdb_dump_db_context
*c
= (struct ctdb_dump_db_context
*)p
;
2319 struct ctdb_ltdb_header
*h
= (struct ctdb_ltdb_header
*)data
.dptr
;
2321 fprintf(f
, "key(%u) = \"", (unsigned)key
.dsize
);
2322 for (i
=0;i
<key
.dsize
;i
++) {
2323 if (ISASCII(key
.dptr
[i
])) {
2324 fprintf(f
, "%c", key
.dptr
[i
]);
2326 fprintf(f
, "\\%02X", key
.dptr
[i
]);
2331 fprintf(f
, "dmaster: %u\n", h
->dmaster
);
2332 fprintf(f
, "rsn: %llu\n", (unsigned long long)h
->rsn
);
2334 if (c
->printlmaster
&& c
->ctdb
->vnn_map
!= NULL
) {
2335 fprintf(f
, "lmaster: %u\n", ctdb_lmaster(c
->ctdb
, &key
));
2339 fprintf(f
, "hash: 0x%08x\n", ctdb_hash(&key
));
2342 if (c
->printrecordflags
) {
2343 fprintf(f
, "flags: 0x%08x", h
->flags
);
2344 if (h
->flags
& CTDB_REC_FLAG_MIGRATED_WITH_DATA
) printf(" MIGRATED_WITH_DATA");
2345 if (h
->flags
& CTDB_REC_FLAG_VACUUM_MIGRATED
) printf(" VACUUM_MIGRATED");
2346 if (h
->flags
& CTDB_REC_FLAG_AUTOMATIC
) printf(" AUTOMATIC");
2347 if (h
->flags
& CTDB_REC_RO_HAVE_DELEGATIONS
) printf(" RO_HAVE_DELEGATIONS");
2348 if (h
->flags
& CTDB_REC_RO_HAVE_READONLY
) printf(" RO_HAVE_READONLY");
2349 if (h
->flags
& CTDB_REC_RO_REVOKING_READONLY
) printf(" RO_REVOKING_READONLY");
2350 if (h
->flags
& CTDB_REC_RO_REVOKE_COMPLETE
) printf(" RO_REVOKE_COMPLETE");
2354 if (c
->printdatasize
) {
2355 fprintf(f
, "data size: %u\n", (unsigned)data
.dsize
);
2357 fprintf(f
, "data(%u) = \"", (unsigned)(data
.dsize
- sizeof(*h
)));
2358 for (i
=sizeof(*h
);i
<data
.dsize
;i
++) {
2359 if (ISASCII(data
.dptr
[i
])) {
2360 fprintf(f
, "%c", data
.dptr
[i
]);
2362 fprintf(f
, "\\%02X", data
.dptr
[i
]);
2374 convenience function to list all keys to stdout
2376 int ctdb_dump_db(struct ctdb_db_context
*ctdb_db
,
2377 struct ctdb_dump_db_context
*ctx
)
2379 return ctdb_traverse_ext(ctdb_db
, ctdb_dumpdb_record
,
2380 ctx
->printemptyrecords
, ctx
);
2384 get the pid of a ctdb daemon
2386 int ctdb_ctrl_getpid(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t *pid
)
2391 ret
= ctdb_control(ctdb
, destnode
, 0,
2392 CTDB_CONTROL_GET_PID
, 0, tdb_null
,
2393 NULL
, NULL
, &res
, &timeout
, NULL
);
2395 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getpid failed\n"));
2404 /* Freeze all databases */
2405 int ctdb_ctrl_freeze(struct ctdb_context
*ctdb
, struct timeval timeout
,
2411 ret
= ctdb_control(ctdb
, destnode
, 0,
2412 CTDB_CONTROL_FREEZE
, 0, tdb_null
,
2413 NULL
, NULL
, &res
, &timeout
, NULL
);
2414 if (ret
!= 0 || res
!= 0) {
2415 DEBUG(DEBUG_ERR
, ("ctdb_ctrl_freeze_priority failed\n"));
2423 get pnn of a node, or -1
2425 int ctdb_ctrl_getpnn(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
)
2430 ret
= ctdb_control(ctdb
, destnode
, 0,
2431 CTDB_CONTROL_GET_PNN
, 0, tdb_null
,
2432 NULL
, NULL
, &res
, &timeout
, NULL
);
2434 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getpnn failed\n"));
2443 sent to a node to make it take over an ip address
2445 int ctdb_ctrl_takeover_ip(struct ctdb_context
*ctdb
, struct timeval timeout
,
2446 uint32_t destnode
, struct ctdb_public_ip
*ip
)
2452 data
.dsize
= sizeof(*ip
);
2453 data
.dptr
= (uint8_t *)ip
;
2455 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_TAKEOVER_IP
, 0,
2456 data
, NULL
, NULL
, &res
, &timeout
, NULL
);
2457 if (ret
!= 0 || res
!= 0) {
2458 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for takeover_ip failed\n"));
2467 sent to a node to make it release an ip address
2469 int ctdb_ctrl_release_ip(struct ctdb_context
*ctdb
, struct timeval timeout
,
2470 uint32_t destnode
, struct ctdb_public_ip
*ip
)
2476 data
.dsize
= sizeof(*ip
);
2477 data
.dptr
= (uint8_t *)ip
;
2479 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_RELEASE_IP
, 0,
2480 data
, NULL
, NULL
, &res
, &timeout
, NULL
);
2481 if (ret
!= 0 || res
!= 0) {
2482 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for release_ip failed\n"));
2493 int ctdb_ctrl_get_tunable(struct ctdb_context
*ctdb
,
2494 struct timeval timeout
,
2496 const char *name
, uint32_t *value
)
2498 struct ctdb_control_get_tunable
*t
;
2499 TDB_DATA data
, outdata
;
2503 data
.dsize
= offsetof(struct ctdb_control_get_tunable
, name
) + strlen(name
) + 1;
2504 data
.dptr
= talloc_size(ctdb
, data
.dsize
);
2505 CTDB_NO_MEMORY(ctdb
, data
.dptr
);
2507 t
= (struct ctdb_control_get_tunable
*)data
.dptr
;
2508 t
->length
= strlen(name
)+1;
2509 memcpy(t
->name
, name
, t
->length
);
2511 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_TUNABLE
, 0, data
, ctdb
,
2512 &outdata
, &res
, &timeout
, NULL
);
2513 talloc_free(data
.dptr
);
2514 if (ret
!= 0 || res
!= 0) {
2515 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get_tunable failed\n"));
2516 return ret
!= 0 ? ret
: res
;
2519 if (outdata
.dsize
!= sizeof(uint32_t)) {
2520 DEBUG(DEBUG_ERR
,("Invalid return data in get_tunable\n"));
2521 talloc_free(outdata
.dptr
);
2525 *value
= *(uint32_t *)outdata
.dptr
;
2526 talloc_free(outdata
.dptr
);
2534 int ctdb_ctrl_set_tunable(struct ctdb_context
*ctdb
,
2535 struct timeval timeout
,
2537 const char *name
, uint32_t value
)
2539 struct ctdb_tunable_old
*t
;
2544 data
.dsize
= offsetof(struct ctdb_tunable_old
, name
) + strlen(name
) + 1;
2545 data
.dptr
= talloc_size(ctdb
, data
.dsize
);
2546 CTDB_NO_MEMORY(ctdb
, data
.dptr
);
2548 t
= (struct ctdb_tunable_old
*)data
.dptr
;
2549 t
->length
= strlen(name
)+1;
2550 memcpy(t
->name
, name
, t
->length
);
2553 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_SET_TUNABLE
, 0, data
, NULL
,
2554 NULL
, &res
, &timeout
, NULL
);
2555 talloc_free(data
.dptr
);
2556 if ((ret
!= 0) || (res
== -1)) {
2557 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for set_tunable failed\n"));
2567 int ctdb_ctrl_list_tunables(struct ctdb_context
*ctdb
,
2568 struct timeval timeout
,
2570 TALLOC_CTX
*mem_ctx
,
2571 const char ***list
, uint32_t *count
)
2576 struct ctdb_control_list_tunable
*t
;
2579 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_LIST_TUNABLES
, 0, tdb_null
,
2580 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
2581 if (ret
!= 0 || res
!= 0) {
2582 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for list_tunables failed\n"));
2586 t
= (struct ctdb_control_list_tunable
*)outdata
.dptr
;
2587 if (outdata
.dsize
< offsetof(struct ctdb_control_list_tunable
, data
) ||
2588 t
->length
> outdata
.dsize
-offsetof(struct ctdb_control_list_tunable
, data
)) {
2589 DEBUG(DEBUG_ERR
,("Invalid data in list_tunables reply\n"));
2590 talloc_free(outdata
.dptr
);
2594 p
= talloc_strndup(mem_ctx
, (char *)t
->data
, t
->length
);
2595 CTDB_NO_MEMORY(ctdb
, p
);
2597 talloc_free(outdata
.dptr
);
2602 for (s
=strtok_r(p
, ":", &ptr
); s
; s
=strtok_r(NULL
, ":", &ptr
)) {
2603 (*list
) = talloc_realloc(mem_ctx
, *list
, const char *, 1+(*count
));
2604 CTDB_NO_MEMORY(ctdb
, *list
);
2605 (*list
)[*count
] = talloc_strdup(*list
, s
);
2606 CTDB_NO_MEMORY(ctdb
, (*list
)[*count
]);
2616 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context
*ctdb
,
2617 struct timeval timeout
, uint32_t destnode
,
2618 TALLOC_CTX
*mem_ctx
,
2620 struct ctdb_public_ip_list_old
**ips
)
2626 ret
= ctdb_control(ctdb
, destnode
, 0,
2627 CTDB_CONTROL_GET_PUBLIC_IPS
, flags
, tdb_null
,
2628 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
2629 if (ret
!= 0 || res
!= 0) {
2630 DEBUG(DEBUG_ERR
,(__location__
2631 " ctdb_control for getpublicips failed ret:%d res:%d\n",
2636 *ips
= (struct ctdb_public_ip_list_old
*)talloc_memdup(mem_ctx
, outdata
.dptr
, outdata
.dsize
);
2637 talloc_free(outdata
.dptr
);
2642 int ctdb_ctrl_get_public_ips(struct ctdb_context
*ctdb
,
2643 struct timeval timeout
, uint32_t destnode
,
2644 TALLOC_CTX
*mem_ctx
,
2645 struct ctdb_public_ip_list_old
**ips
)
2647 return ctdb_ctrl_get_public_ips_flags(ctdb
, timeout
,
2652 int ctdb_ctrl_get_public_ip_info(struct ctdb_context
*ctdb
,
2653 struct timeval timeout
, uint32_t destnode
,
2654 TALLOC_CTX
*mem_ctx
,
2655 const ctdb_sock_addr
*addr
,
2656 struct ctdb_public_ip_info_old
**_info
)
2662 struct ctdb_public_ip_info_old
*info
;
2666 indata
.dptr
= discard_const_p(uint8_t, addr
);
2667 indata
.dsize
= sizeof(*addr
);
2669 ret
= ctdb_control(ctdb
, destnode
, 0,
2670 CTDB_CONTROL_GET_PUBLIC_IP_INFO
, 0, indata
,
2671 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
2672 if (ret
!= 0 || res
!= 0) {
2673 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get public ip info "
2674 "failed ret:%d res:%d\n",
2679 len
= offsetof(struct ctdb_public_ip_info_old
, ifaces
);
2680 if (len
> outdata
.dsize
) {
2681 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get public ip info "
2682 "returned invalid data with size %u > %u\n",
2683 (unsigned int)outdata
.dsize
,
2684 (unsigned int)len
));
2685 dump_data(DEBUG_DEBUG
, outdata
.dptr
, outdata
.dsize
);
2689 info
= (struct ctdb_public_ip_info_old
*)outdata
.dptr
;
2690 len
+= info
->num
*sizeof(struct ctdb_iface
);
2692 if (len
> outdata
.dsize
) {
2693 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get public ip info "
2694 "returned invalid data with size %u > %u\n",
2695 (unsigned int)outdata
.dsize
,
2696 (unsigned int)len
));
2697 dump_data(DEBUG_DEBUG
, outdata
.dptr
, outdata
.dsize
);
2701 /* make sure we null terminate the returned strings */
2702 for (i
=0; i
< info
->num
; i
++) {
2703 info
->ifaces
[i
].name
[CTDB_IFACE_SIZE
] = '\0';
2706 *_info
= (struct ctdb_public_ip_info_old
*)talloc_memdup(mem_ctx
,
2709 talloc_free(outdata
.dptr
);
2710 if (*_info
== NULL
) {
2711 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get public ip info "
2712 "talloc_memdup size %u failed\n",
2713 (unsigned int)outdata
.dsize
));
2720 int ctdb_ctrl_get_ifaces(struct ctdb_context
*ctdb
,
2721 struct timeval timeout
, uint32_t destnode
,
2722 TALLOC_CTX
*mem_ctx
,
2723 struct ctdb_iface_list_old
**_ifaces
)
2728 struct ctdb_iface_list_old
*ifaces
;
2732 ret
= ctdb_control(ctdb
, destnode
, 0,
2733 CTDB_CONTROL_GET_IFACES
, 0, tdb_null
,
2734 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
2735 if (ret
!= 0 || res
!= 0) {
2736 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
2737 "failed ret:%d res:%d\n",
2742 len
= offsetof(struct ctdb_iface_list_old
, ifaces
);
2743 if (len
> outdata
.dsize
) {
2744 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
2745 "returned invalid data with size %u > %u\n",
2746 (unsigned int)outdata
.dsize
,
2747 (unsigned int)len
));
2748 dump_data(DEBUG_DEBUG
, outdata
.dptr
, outdata
.dsize
);
2752 ifaces
= (struct ctdb_iface_list_old
*)outdata
.dptr
;
2753 len
+= ifaces
->num
*sizeof(struct ctdb_iface
);
2755 if (len
> outdata
.dsize
) {
2756 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
2757 "returned invalid data with size %u > %u\n",
2758 (unsigned int)outdata
.dsize
,
2759 (unsigned int)len
));
2760 dump_data(DEBUG_DEBUG
, outdata
.dptr
, outdata
.dsize
);
2764 /* make sure we null terminate the returned strings */
2765 for (i
=0; i
< ifaces
->num
; i
++) {
2766 ifaces
->ifaces
[i
].name
[CTDB_IFACE_SIZE
] = '\0';
2769 *_ifaces
= (struct ctdb_iface_list_old
*)talloc_memdup(mem_ctx
,
2772 talloc_free(outdata
.dptr
);
2773 if (*_ifaces
== NULL
) {
2774 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get ifaces "
2775 "talloc_memdup size %u failed\n",
2776 (unsigned int)outdata
.dsize
));
2783 int ctdb_ctrl_set_iface_link(struct ctdb_context
*ctdb
,
2784 struct timeval timeout
, uint32_t destnode
,
2785 TALLOC_CTX
*mem_ctx
,
2786 const struct ctdb_iface
*info
)
2792 indata
.dptr
= discard_const_p(uint8_t, info
);
2793 indata
.dsize
= sizeof(*info
);
2795 ret
= ctdb_control(ctdb
, destnode
, 0,
2796 CTDB_CONTROL_SET_IFACE_LINK_STATE
, 0, indata
,
2797 mem_ctx
, NULL
, &res
, &timeout
, NULL
);
2798 if (ret
!= 0 || res
!= 0) {
2799 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for set iface link "
2800 "failed ret:%d res:%d\n",
2809 set/clear the permanent disabled bit on a remote node
2811 int ctdb_ctrl_modflags(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
,
2812 uint32_t set
, uint32_t clear
)
2816 struct ctdb_node_map_old
*nodemap
=NULL
;
2817 struct ctdb_node_flag_change c
;
2818 TALLOC_CTX
*tmp_ctx
= talloc_new(ctdb
);
2823 /* find the recovery master */
2824 ret
= ctdb_ctrl_getrecmaster(ctdb
, tmp_ctx
, timeout
, CTDB_CURRENT_NODE
, &recmaster
);
2826 DEBUG(DEBUG_ERR
, (__location__
" Unable to get recmaster from local node\n"));
2827 talloc_free(tmp_ctx
);
2832 /* read the node flags from the recmaster */
2833 ret
= ctdb_ctrl_getnodemap(ctdb
, timeout
, recmaster
, tmp_ctx
, &nodemap
);
2835 DEBUG(DEBUG_ERR
, (__location__
" Unable to get nodemap from node %u\n", destnode
));
2836 talloc_free(tmp_ctx
);
2839 if (destnode
>= nodemap
->num
) {
2840 DEBUG(DEBUG_ERR
,(__location__
" Nodemap from recmaster does not contain node %d\n", destnode
));
2841 talloc_free(tmp_ctx
);
2846 c
.old_flags
= nodemap
->nodes
[destnode
].flags
;
2847 c
.new_flags
= c
.old_flags
;
2849 c
.new_flags
&= ~clear
;
2851 data
.dsize
= sizeof(c
);
2852 data
.dptr
= (unsigned char *)&c
;
2854 /* send the flags update to all connected nodes */
2855 nodes
= list_of_connected_nodes(ctdb
, nodemap
, tmp_ctx
, true);
2857 if (ctdb_client_async_control(ctdb
, CTDB_CONTROL_MODIFY_FLAGS
,
2859 timeout
, false, data
,
2862 DEBUG(DEBUG_ERR
, (__location__
" Unable to update nodeflags on remote nodes\n"));
2864 talloc_free(tmp_ctx
);
2868 talloc_free(tmp_ctx
);
2876 int ctdb_ctrl_get_all_tunables(struct ctdb_context
*ctdb
,
2877 struct timeval timeout
,
2879 struct ctdb_tunable_list
*tunables
)
2885 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_GET_ALL_TUNABLES
, 0, tdb_null
, ctdb
,
2886 &outdata
, &res
, &timeout
, NULL
);
2887 if (ret
!= 0 || res
!= 0) {
2888 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get all tunables failed\n"));
2892 if (outdata
.dsize
!= sizeof(*tunables
)) {
2893 DEBUG(DEBUG_ERR
,(__location__
" bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2894 (unsigned)outdata
.dsize
, (unsigned)sizeof(*tunables
)));
2898 *tunables
= *(struct ctdb_tunable_list
*)outdata
.dptr
;
2899 talloc_free(outdata
.dptr
);
2904 add a public address to a node
2906 int ctdb_ctrl_add_public_ip(struct ctdb_context
*ctdb
,
2907 struct timeval timeout
, uint32_t destnode
,
2908 struct ctdb_addr_info_old
*pub
)
2914 data
.dsize
= offsetof(struct ctdb_addr_info_old
, iface
) + pub
->len
;
2915 data
.dptr
= (unsigned char *)pub
;
2917 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_ADD_PUBLIC_IP
, 0, data
, NULL
,
2918 NULL
, &res
, &timeout
, NULL
);
2919 if (ret
!= 0 || res
!= 0) {
2920 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for add_public_ip failed\n"));
2928 delete a public address from a node
2930 int ctdb_ctrl_del_public_ip(struct ctdb_context
*ctdb
,
2931 struct timeval timeout
, uint32_t destnode
,
2932 struct ctdb_addr_info_old
*pub
)
2938 data
.dsize
= offsetof(struct ctdb_addr_info_old
, iface
) + pub
->len
;
2939 data
.dptr
= (unsigned char *)pub
;
2941 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_DEL_PUBLIC_IP
, 0, data
, NULL
,
2942 NULL
, &res
, &timeout
, NULL
);
2943 if (ret
!= 0 || res
!= 0) {
2944 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for del_public_ip failed\n"));
2954 int ctdb_ctrl_gratious_arp(struct ctdb_context
*ctdb
,
2955 struct timeval timeout
, uint32_t destnode
,
2956 ctdb_sock_addr
*addr
, const char *ifname
)
2961 struct ctdb_addr_info_old
*gratious_arp
;
2962 TALLOC_CTX
*tmp_ctx
= talloc_new(ctdb
);
2965 len
= strlen(ifname
)+1;
2966 gratious_arp
= talloc_size(tmp_ctx
,
2967 offsetof(struct ctdb_addr_info_old
, iface
) + len
);
2968 CTDB_NO_MEMORY(ctdb
, gratious_arp
);
2970 gratious_arp
->addr
= *addr
;
2971 gratious_arp
->len
= len
;
2972 memcpy(&gratious_arp
->iface
[0], ifname
, len
);
2975 data
.dsize
= offsetof(struct ctdb_addr_info_old
, iface
) + len
;
2976 data
.dptr
= (unsigned char *)gratious_arp
;
2978 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_SEND_GRATUITOUS_ARP
, 0, data
, NULL
,
2979 NULL
, &res
, &timeout
, NULL
);
2980 if (ret
!= 0 || res
!= 0) {
2981 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for gratious_arp failed\n"));
2982 talloc_free(tmp_ctx
);
2986 talloc_free(tmp_ctx
);
2991 get a list of all tcp tickles that a node knows about for a particular vnn
2993 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context
*ctdb
,
2994 struct timeval timeout
, uint32_t destnode
,
2995 TALLOC_CTX
*mem_ctx
,
2996 ctdb_sock_addr
*addr
,
2997 struct ctdb_tickle_list_old
**list
)
3000 TDB_DATA data
, outdata
;
3003 data
.dptr
= (uint8_t*)addr
;
3004 data
.dsize
= sizeof(ctdb_sock_addr
);
3006 ret
= ctdb_control(ctdb
, destnode
, 0,
3007 CTDB_CONTROL_GET_TCP_TICKLE_LIST
, 0, data
,
3008 mem_ctx
, &outdata
, &status
, NULL
, NULL
);
3009 if (ret
!= 0 || status
!= 0) {
3010 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for get tcp tickles failed\n"));
3014 *list
= (struct ctdb_tickle_list_old
*)outdata
.dptr
;
3020 initialise the ctdb daemon for client applications
3022 NOTE: In current code the daemon does not fork. This is for testing purposes only
3023 and to simplify the code.
3025 struct ctdb_context
*ctdb_init(struct tevent_context
*ev
)
3028 struct ctdb_context
*ctdb
;
3030 ctdb
= talloc_zero(ev
, struct ctdb_context
);
3032 DEBUG(DEBUG_ERR
,(__location__
" talloc_zero failed.\n"));
3036 /* Wrap early to exercise code. */
3037 ret
= reqid_init(ctdb
, INT_MAX
-200, &ctdb
->idr
);
3039 DEBUG(DEBUG_ERR
, ("reqid_init failed (%s)\n", strerror(ret
)));
3044 ret
= srvid_init(ctdb
, &ctdb
->srv
);
3046 DEBUG(DEBUG_ERR
, ("srvid_init failed (%s)\n", strerror(ret
)));
3051 ret
= ctdb_set_socketname(ctdb
, CTDB_SOCKET
);
3053 DEBUG(DEBUG_ERR
,(__location__
" ctdb_set_socketname failed.\n"));
3058 ctdb
->statistics
.statistics_start_time
= timeval_current();
3067 void ctdb_set_flags(struct ctdb_context
*ctdb
, unsigned flags
)
3069 ctdb
->flags
|= flags
;
3073 setup the local socket name
3075 int ctdb_set_socketname(struct ctdb_context
*ctdb
, const char *socketname
)
3077 ctdb
->daemon
.name
= talloc_strdup(ctdb
, socketname
);
3078 CTDB_NO_MEMORY(ctdb
, ctdb
->daemon
.name
);
3083 const char *ctdb_get_socketname(struct ctdb_context
*ctdb
)
3085 return ctdb
->daemon
.name
;
3089 return the pnn of this node
3091 uint32_t ctdb_get_pnn(struct ctdb_context
*ctdb
)
3098 get the uptime of a remote node
3100 struct ctdb_client_control_state
*
3101 ctdb_ctrl_uptime_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
)
3103 return ctdb_control_send(ctdb
, destnode
, 0,
3104 CTDB_CONTROL_UPTIME
, 0, tdb_null
,
3105 mem_ctx
, &timeout
, NULL
);
3108 int ctdb_ctrl_uptime_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, struct ctdb_uptime
**uptime
)
3114 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, &outdata
, &res
, NULL
);
3115 if (ret
!= 0 || res
!= 0) {
3116 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_uptime_recv failed\n"));
3120 *uptime
= (struct ctdb_uptime
*)talloc_steal(mem_ctx
, outdata
.dptr
);
3125 int ctdb_ctrl_uptime(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
, struct ctdb_uptime
**uptime
)
3127 struct ctdb_client_control_state
*state
;
3129 state
= ctdb_ctrl_uptime_send(ctdb
, mem_ctx
, timeout
, destnode
);
3130 return ctdb_ctrl_uptime_recv(ctdb
, mem_ctx
, state
, uptime
);
3134 send a control to execute the "recovered" event script on a node
3136 int ctdb_ctrl_end_recovery(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
)
3141 ret
= ctdb_control(ctdb
, destnode
, 0,
3142 CTDB_CONTROL_END_RECOVERY
, 0, tdb_null
,
3143 NULL
, NULL
, &status
, &timeout
, NULL
);
3144 if (ret
!= 0 || status
!= 0) {
3145 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for end_recovery failed\n"));
3153 callback for the async helpers used when sending the same control
3154 to multiple nodes in parallell.
3156 static void async_callback(struct ctdb_client_control_state
*state
)
3158 struct client_async_data
*data
= talloc_get_type(state
->async
.private_data
, struct client_async_data
);
3159 struct ctdb_context
*ctdb
= talloc_get_type(state
->ctdb
, struct ctdb_context
);
3163 uint32_t destnode
= state
->c
->hdr
.destnode
;
3166 outdata
.dptr
= NULL
;
3168 /* one more node has responded with recmode data */
3171 /* if we failed to push the db, then return an error and let
3172 the main loop try again.
3174 if (state
->state
!= CTDB_CONTROL_DONE
) {
3175 if ( !data
->dont_log_errors
) {
3176 DEBUG(DEBUG_ERR
,("Async operation failed with state %d, opcode:%u\n", state
->state
, data
->opcode
));
3179 if (state
->state
== CTDB_CONTROL_TIMEOUT
) {
3184 if (data
->fail_callback
) {
3185 data
->fail_callback(ctdb
, destnode
, res
, outdata
,
3186 data
->callback_data
);
3191 state
->async
.fn
= NULL
;
3193 ret
= ctdb_control_recv(ctdb
, state
, data
, &outdata
, &res
, NULL
);
3194 if ((ret
!= 0) || (res
!= 0)) {
3195 if ( !data
->dont_log_errors
) {
3196 DEBUG(DEBUG_ERR
,("Async operation failed with ret=%d res=%d opcode=%u\n", ret
, (int)res
, data
->opcode
));
3199 if (data
->fail_callback
) {
3200 data
->fail_callback(ctdb
, destnode
, res
, outdata
,
3201 data
->callback_data
);
3204 if ((ret
== 0) && (data
->callback
!= NULL
)) {
3205 data
->callback(ctdb
, destnode
, res
, outdata
,
3206 data
->callback_data
);
3211 void ctdb_client_async_add(struct client_async_data
*data
, struct ctdb_client_control_state
*state
)
3213 /* set up the callback functions */
3214 state
->async
.fn
= async_callback
;
3215 state
->async
.private_data
= data
;
3217 /* one more control to wait for to complete */
3222 /* wait for up to the maximum number of seconds allowed
3223 or until all nodes we expect a response from has replied
3225 int ctdb_client_async_wait(struct ctdb_context
*ctdb
, struct client_async_data
*data
)
3227 while (data
->count
> 0) {
3228 tevent_loop_once(ctdb
->ev
);
3230 if (data
->fail_count
!= 0) {
3231 if (!data
->dont_log_errors
) {
3232 DEBUG(DEBUG_ERR
,("Async wait failed - fail_count=%u\n",
3242 perform a simple control on the listed nodes
3243 The control cannot return data
3245 int ctdb_client_async_control(struct ctdb_context
*ctdb
,
3246 enum ctdb_controls opcode
,
3249 struct timeval timeout
,
3250 bool dont_log_errors
,
3252 client_async_callback client_callback
,
3253 client_async_callback fail_callback
,
3254 void *callback_data
)
3256 struct client_async_data
*async_data
;
3257 struct ctdb_client_control_state
*state
;
3260 async_data
= talloc_zero(ctdb
, struct client_async_data
);
3261 CTDB_NO_MEMORY_FATAL(ctdb
, async_data
);
3262 async_data
->dont_log_errors
= dont_log_errors
;
3263 async_data
->callback
= client_callback
;
3264 async_data
->fail_callback
= fail_callback
;
3265 async_data
->callback_data
= callback_data
;
3266 async_data
->opcode
= opcode
;
3268 num_nodes
= talloc_get_size(nodes
) / sizeof(uint32_t);
3270 /* loop over all nodes and send an async control to each of them */
3271 for (j
=0; j
<num_nodes
; j
++) {
3272 uint32_t pnn
= nodes
[j
];
3274 state
= ctdb_control_send(ctdb
, pnn
, srvid
, opcode
,
3275 0, data
, async_data
, &timeout
, NULL
);
3276 if (state
== NULL
) {
3277 DEBUG(DEBUG_ERR
,(__location__
" Failed to call async control %u\n", (unsigned)opcode
));
3278 talloc_free(async_data
);
3282 ctdb_client_async_add(async_data
, state
);
3285 if (ctdb_client_async_wait(ctdb
, async_data
) != 0) {
3286 talloc_free(async_data
);
3290 talloc_free(async_data
);
3294 uint32_t *list_of_vnnmap_nodes(struct ctdb_context
*ctdb
,
3295 struct ctdb_vnn_map
*vnn_map
,
3296 TALLOC_CTX
*mem_ctx
,
3299 int i
, j
, num_nodes
;
3302 for (i
=num_nodes
=0;i
<vnn_map
->size
;i
++) {
3303 if (vnn_map
->map
[i
] == ctdb
->pnn
&& !include_self
) {
3309 nodes
= talloc_array(mem_ctx
, uint32_t, num_nodes
);
3310 CTDB_NO_MEMORY_FATAL(ctdb
, nodes
);
3312 for (i
=j
=0;i
<vnn_map
->size
;i
++) {
3313 if (vnn_map
->map
[i
] == ctdb
->pnn
&& !include_self
) {
3316 nodes
[j
++] = vnn_map
->map
[i
];
3322 /* Get list of nodes not including those with flags specified by mask.
3323 * If exclude_pnn is not -1 then exclude that pnn from the list.
3325 uint32_t *list_of_nodes(struct ctdb_context
*ctdb
,
3326 struct ctdb_node_map_old
*node_map
,
3327 TALLOC_CTX
*mem_ctx
,
3331 int i
, j
, num_nodes
;
3334 for (i
=num_nodes
=0;i
<node_map
->num
;i
++) {
3335 if (node_map
->nodes
[i
].flags
& mask
) {
3338 if (node_map
->nodes
[i
].pnn
== exclude_pnn
) {
3344 nodes
= talloc_array(mem_ctx
, uint32_t, num_nodes
);
3345 CTDB_NO_MEMORY_FATAL(ctdb
, nodes
);
3347 for (i
=j
=0;i
<node_map
->num
;i
++) {
3348 if (node_map
->nodes
[i
].flags
& mask
) {
3351 if (node_map
->nodes
[i
].pnn
== exclude_pnn
) {
3354 nodes
[j
++] = node_map
->nodes
[i
].pnn
;
3360 uint32_t *list_of_active_nodes(struct ctdb_context
*ctdb
,
3361 struct ctdb_node_map_old
*node_map
,
3362 TALLOC_CTX
*mem_ctx
,
3365 return list_of_nodes(ctdb
, node_map
, mem_ctx
, NODE_FLAGS_INACTIVE
,
3366 include_self
? -1 : ctdb
->pnn
);
3369 uint32_t *list_of_connected_nodes(struct ctdb_context
*ctdb
,
3370 struct ctdb_node_map_old
*node_map
,
3371 TALLOC_CTX
*mem_ctx
,
3374 return list_of_nodes(ctdb
, node_map
, mem_ctx
, NODE_FLAGS_DISCONNECTED
,
3375 include_self
? -1 : ctdb
->pnn
);
3379 this is used to test if a pnn lock exists and if it exists will return
3380 the number of connections that pnn has reported or -1 if that recovery
3381 daemon is not running.
3384 ctdb_read_pnn_lock(int fd
, int32_t pnn
)
3389 lock
.l_type
= F_WRLCK
;
3390 lock
.l_whence
= SEEK_SET
;
3395 if (fcntl(fd
, F_GETLK
, &lock
) != 0) {
3396 DEBUG(DEBUG_ERR
, (__location__
" F_GETLK failed with %s\n", strerror(errno
)));
3400 if (lock
.l_type
== F_UNLCK
) {
3404 if (pread(fd
, &c
, 1, pnn
) == -1) {
3405 DEBUG(DEBUG_CRIT
,(__location__
" failed read pnn count - %s\n", strerror(errno
)));
3413 get capabilities of a remote node
3415 struct ctdb_client_control_state
*
3416 ctdb_ctrl_getcapabilities_send(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct timeval timeout
, uint32_t destnode
)
3418 return ctdb_control_send(ctdb
, destnode
, 0,
3419 CTDB_CONTROL_GET_CAPABILITIES
, 0, tdb_null
,
3420 mem_ctx
, &timeout
, NULL
);
3423 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context
*ctdb
, TALLOC_CTX
*mem_ctx
, struct ctdb_client_control_state
*state
, uint32_t *capabilities
)
3429 ret
= ctdb_control_recv(ctdb
, state
, mem_ctx
, &outdata
, &res
, NULL
);
3430 if ( (ret
!= 0) || (res
!= 0) ) {
3431 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_getcapabilities_recv failed\n"));
3436 *capabilities
= *((uint32_t *)outdata
.dptr
);
3442 int ctdb_ctrl_getcapabilities(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t *capabilities
)
3444 struct ctdb_client_control_state
*state
;
3445 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
3448 state
= ctdb_ctrl_getcapabilities_send(ctdb
, tmp_ctx
, timeout
, destnode
);
3449 ret
= ctdb_ctrl_getcapabilities_recv(ctdb
, tmp_ctx
, state
, capabilities
);
3450 talloc_free(tmp_ctx
);
3454 static void get_capabilities_callback(struct ctdb_context
*ctdb
,
3455 uint32_t node_pnn
, int32_t res
,
3456 TDB_DATA outdata
, void *callback_data
)
3458 struct ctdb_node_capabilities
*caps
=
3459 talloc_get_type(callback_data
,
3460 struct ctdb_node_capabilities
);
3462 if ( (outdata
.dsize
!= sizeof(uint32_t)) || (outdata
.dptr
== NULL
) ) {
3463 DEBUG(DEBUG_ERR
, (__location__
" Invalid length/pointer for getcap callback : %u %p\n", (unsigned)outdata
.dsize
, outdata
.dptr
));
3467 if (node_pnn
>= talloc_array_length(caps
)) {
3469 (__location__
" unexpected PNN %u\n", node_pnn
));
3473 caps
[node_pnn
].retrieved
= true;
3474 caps
[node_pnn
].capabilities
= *((uint32_t *)outdata
.dptr
);
3477 struct ctdb_node_capabilities
*
3478 ctdb_get_capabilities(struct ctdb_context
*ctdb
,
3479 TALLOC_CTX
*mem_ctx
,
3480 struct timeval timeout
,
3481 struct ctdb_node_map_old
*nodemap
)
3485 struct ctdb_node_capabilities
*ret
;
3487 nodes
= list_of_active_nodes(ctdb
, nodemap
, mem_ctx
, true);
3489 ret
= talloc_array(mem_ctx
, struct ctdb_node_capabilities
,
3491 CTDB_NO_MEMORY_NULL(ctdb
, ret
);
3492 /* Prepopulate the expected PNNs */
3493 for (i
= 0; i
< talloc_array_length(ret
); i
++) {
3494 ret
[i
].retrieved
= false;
3497 res
= ctdb_client_async_control(ctdb
, CTDB_CONTROL_GET_CAPABILITIES
,
3500 get_capabilities_callback
, NULL
,
3504 (__location__
" Failed to read node capabilities.\n"));
3512 ctdb_get_node_capabilities(struct ctdb_node_capabilities
*caps
,
3515 if (pnn
< talloc_array_length(caps
) && caps
[pnn
].retrieved
) {
3516 return &caps
[pnn
].capabilities
;
3522 bool ctdb_node_has_capabilities(struct ctdb_node_capabilities
*caps
,
3524 uint32_t capabilities_required
)
3526 uint32_t *capp
= ctdb_get_node_capabilities(caps
, pnn
);
3527 return (capp
!= NULL
) &&
3528 ((*capp
& capabilities_required
) == capabilities_required
);
3532 static struct ctdb_server_id
server_id_fetch(struct ctdb_context
*ctdb
, uint32_t reqid
)
3534 struct ctdb_server_id id
;
3538 id
.vnn
= ctdb_get_pnn(ctdb
);
3539 id
.unique_id
= id
.vnn
;
3540 id
.unique_id
= (id
.unique_id
<< 32) | reqid
;
3545 /* This is basically a copy from Samba's server_id.*. However, a
3546 * dependency chain stops us from using Samba's version, so use a
3547 * renamed copy until a better solution is found. */
3548 static bool ctdb_server_id_equal(struct ctdb_server_id
*id1
, struct ctdb_server_id
*id2
)
3550 if (id1
->pid
!= id2
->pid
) {
3554 if (id1
->task_id
!= id2
->task_id
) {
3558 if (id1
->vnn
!= id2
->vnn
) {
3562 if (id1
->unique_id
!= id2
->unique_id
) {
3569 static bool server_id_exists(struct ctdb_context
*ctdb
,
3570 struct ctdb_server_id
*id
)
3574 ret
= ctdb_ctrl_process_exists(ctdb
, id
->vnn
, id
->pid
);
3582 static bool g_lock_parse(TALLOC_CTX
*mem_ctx
, TDB_DATA data
,
3583 struct ctdb_g_lock_list
**locks
)
3585 struct ctdb_g_lock_list
*recs
;
3587 recs
= talloc_zero(mem_ctx
, struct ctdb_g_lock_list
);
3592 if (data
.dsize
== 0) {
3596 if (data
.dsize
% sizeof(struct ctdb_g_lock
) != 0) {
3597 DEBUG(DEBUG_ERR
, (__location__
"invalid data size %lu in g_lock record\n",
3598 (unsigned long)data
.dsize
));
3603 recs
->num
= data
.dsize
/ sizeof(struct ctdb_g_lock
);
3604 recs
->lock
= talloc_memdup(mem_ctx
, data
.dptr
, data
.dsize
);
3605 if (recs
->lock
== NULL
) {
3611 if (locks
!= NULL
) {
3619 static bool g_lock_lock(TALLOC_CTX
*mem_ctx
,
3620 struct ctdb_db_context
*ctdb_db
,
3621 const char *keyname
, uint32_t reqid
)
3624 struct ctdb_record_handle
*h
;
3625 struct ctdb_g_lock_list
*locks
;
3626 struct ctdb_server_id id
;
3627 struct timeval t_start
;
3630 key
.dptr
= (uint8_t *)discard_const(keyname
);
3631 key
.dsize
= strlen(keyname
) + 1;
3633 t_start
= timeval_current();
3636 /* Keep trying for an hour. */
3637 if (timeval_elapsed(&t_start
) > 3600) {
3641 h
= ctdb_fetch_lock(ctdb_db
, mem_ctx
, key
, &data
);
3646 if (!g_lock_parse(h
, data
, &locks
)) {
3647 DEBUG(DEBUG_ERR
, ("g_lock: error parsing locks\n"));
3648 talloc_free(data
.dptr
);
3653 talloc_free(data
.dptr
);
3655 id
= server_id_fetch(ctdb_db
->ctdb
, reqid
);
3658 while (i
< locks
->num
) {
3659 if (ctdb_server_id_equal(&locks
->lock
[i
].sid
, &id
)) {
3660 /* Internal error */
3665 if (!server_id_exists(ctdb_db
->ctdb
, &locks
->lock
[i
].sid
)) {
3666 if (i
< locks
->num
-1) {
3667 locks
->lock
[i
] = locks
->lock
[locks
->num
-1];
3673 /* This entry is locked. */
3674 DEBUG(DEBUG_INFO
, ("g_lock: lock already granted for "
3675 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3676 (unsigned long long)id
.pid
,
3678 (unsigned long long)id
.unique_id
));
3683 locks
->lock
= talloc_realloc(locks
, locks
->lock
, struct ctdb_g_lock
,
3685 if (locks
->lock
== NULL
) {
3690 locks
->lock
[locks
->num
].type
= CTDB_G_LOCK_WRITE
;
3691 locks
->lock
[locks
->num
].sid
= id
;
3694 data
.dptr
= (uint8_t *)locks
->lock
;
3695 data
.dsize
= locks
->num
* sizeof(struct ctdb_g_lock
);
3697 if (ctdb_record_store(h
, data
) != 0) {
3698 DEBUG(DEBUG_ERR
, ("g_lock: failed to write transaction lock for "
3699 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3700 (unsigned long long)id
.pid
,
3702 (unsigned long long)id
.unique_id
));
3707 DEBUG(DEBUG_INFO
, ("g_lock: lock granted for "
3708 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3709 (unsigned long long)id
.pid
,
3711 (unsigned long long)id
.unique_id
));
3717 static bool g_lock_unlock(TALLOC_CTX
*mem_ctx
,
3718 struct ctdb_db_context
*ctdb_db
,
3719 const char *keyname
, uint32_t reqid
)
3722 struct ctdb_record_handle
*h
;
3723 struct ctdb_g_lock_list
*locks
;
3724 struct ctdb_server_id id
;
3728 key
.dptr
= (uint8_t *)discard_const(keyname
);
3729 key
.dsize
= strlen(keyname
) + 1;
3730 h
= ctdb_fetch_lock(ctdb_db
, mem_ctx
, key
, &data
);
3735 if (!g_lock_parse(h
, data
, &locks
)) {
3736 DEBUG(DEBUG_ERR
, ("g_lock: error parsing locks\n"));
3737 talloc_free(data
.dptr
);
3742 talloc_free(data
.dptr
);
3744 id
= server_id_fetch(ctdb_db
->ctdb
, reqid
);
3746 for (i
=0; i
<locks
->num
; i
++) {
3747 if (ctdb_server_id_equal(&locks
->lock
[i
].sid
, &id
)) {
3748 if (i
< locks
->num
-1) {
3749 locks
->lock
[i
] = locks
->lock
[locks
->num
-1];
3758 DEBUG(DEBUG_ERR
, ("g_lock: lock not found\n"));
3763 data
.dptr
= (uint8_t *)locks
->lock
;
3764 data
.dsize
= locks
->num
* sizeof(struct ctdb_g_lock
);
3766 if (ctdb_record_store(h
, data
) != 0) {
3776 struct ctdb_transaction_handle
{
3777 struct ctdb_db_context
*ctdb_db
;
3778 struct ctdb_db_context
*g_lock_db
;
3782 * we store reads and writes done under a transaction:
3783 * - one list stores both reads and writes (m_all)
3784 * - the other just writes (m_write)
3786 struct ctdb_marshall_buffer
*m_all
;
3787 struct ctdb_marshall_buffer
*m_write
;
3790 static int ctdb_transaction_destructor(struct ctdb_transaction_handle
*h
)
3792 g_lock_unlock(h
, h
->g_lock_db
, h
->lock_name
, h
->reqid
);
3793 reqid_remove(h
->ctdb_db
->ctdb
->idr
, h
->reqid
);
3799 * start a transaction on a database
3801 struct ctdb_transaction_handle
*ctdb_transaction_start(struct ctdb_db_context
*ctdb_db
,
3802 TALLOC_CTX
*mem_ctx
)
3804 struct ctdb_transaction_handle
*h
;
3806 h
= talloc_zero(mem_ctx
, struct ctdb_transaction_handle
);
3808 DEBUG(DEBUG_ERR
, (__location__
" memory allocation error\n"));
3812 h
->ctdb_db
= ctdb_db
;
3813 h
->lock_name
= talloc_asprintf(h
, "transaction_db_0x%08x",
3814 (unsigned int)ctdb_db
->db_id
);
3815 if (h
->lock_name
== NULL
) {
3816 DEBUG(DEBUG_ERR
, (__location__
" talloc asprintf failed\n"));
3821 h
->g_lock_db
= ctdb_attach(h
->ctdb_db
->ctdb
, timeval_current_ofs(3,0),
3823 if (!h
->g_lock_db
) {
3824 DEBUG(DEBUG_ERR
, (__location__
" unable to attach to g_lock.tdb\n"));
3829 h
->reqid
= reqid_new(h
->ctdb_db
->ctdb
->idr
, h
);
3831 if (!g_lock_lock(h
, h
->g_lock_db
, h
->lock_name
, h
->reqid
)) {
3832 DEBUG(DEBUG_ERR
, (__location__
" Error locking g_lock.tdb\n"));
3837 talloc_set_destructor(h
, ctdb_transaction_destructor
);
3842 * fetch a record inside a transaction
3844 int ctdb_transaction_fetch(struct ctdb_transaction_handle
*h
,
3845 TALLOC_CTX
*mem_ctx
,
3846 TDB_DATA key
, TDB_DATA
*data
)
3848 struct ctdb_ltdb_header header
;
3851 ZERO_STRUCT(header
);
3853 ret
= ctdb_ltdb_fetch(h
->ctdb_db
, key
, &header
, mem_ctx
, data
);
3854 if (ret
== -1 && header
.dmaster
== (uint32_t)-1) {
3855 /* record doesn't exist yet */
3864 h
->m_all
= ctdb_marshall_add(h
, h
->m_all
, h
->ctdb_db
->db_id
, 1, key
, NULL
, *data
);
3865 if (h
->m_all
== NULL
) {
3866 DEBUG(DEBUG_ERR
,(__location__
" Failed to add to marshalling record\n"));
3874 * stores a record inside a transaction
3876 int ctdb_transaction_store(struct ctdb_transaction_handle
*h
,
3877 TDB_DATA key
, TDB_DATA data
)
3879 TALLOC_CTX
*tmp_ctx
= talloc_new(h
);
3880 struct ctdb_ltdb_header header
;
3884 /* we need the header so we can update the RSN */
3885 ret
= ctdb_ltdb_fetch(h
->ctdb_db
, key
, &header
, tmp_ctx
, &olddata
);
3886 if (ret
== -1 && header
.dmaster
== (uint32_t)-1) {
3887 /* the record doesn't exist - create one with us as dmaster.
3888 This is only safe because we are in a transaction and this
3889 is a persistent database */
3890 ZERO_STRUCT(header
);
3891 } else if (ret
!= 0) {
3892 DEBUG(DEBUG_ERR
,(__location__
" Failed to fetch record\n"));
3893 talloc_free(tmp_ctx
);
3897 if (data
.dsize
== olddata
.dsize
&&
3898 memcmp(data
.dptr
, olddata
.dptr
, data
.dsize
) == 0 &&
3900 /* save writing the same data */
3901 talloc_free(tmp_ctx
);
3905 header
.dmaster
= h
->ctdb_db
->ctdb
->pnn
;
3908 h
->m_all
= ctdb_marshall_add(h
, h
->m_all
, h
->ctdb_db
->db_id
, 0, key
, NULL
, data
);
3909 if (h
->m_all
== NULL
) {
3910 DEBUG(DEBUG_ERR
,(__location__
" Failed to add to marshalling record\n"));
3911 talloc_free(tmp_ctx
);
3915 h
->m_write
= ctdb_marshall_add(h
, h
->m_write
, h
->ctdb_db
->db_id
, 0, key
, &header
, data
);
3916 if (h
->m_write
== NULL
) {
3917 DEBUG(DEBUG_ERR
,(__location__
" Failed to add to marshalling record\n"));
3918 talloc_free(tmp_ctx
);
3922 talloc_free(tmp_ctx
);
3926 static int ctdb_fetch_db_seqnum(struct ctdb_db_context
*ctdb_db
, uint64_t *seqnum
)
3928 const char *keyname
= CTDB_DB_SEQNUM_KEY
;
3930 struct ctdb_ltdb_header header
;
3933 key
.dptr
= (uint8_t *)discard_const(keyname
);
3934 key
.dsize
= strlen(keyname
) + 1;
3936 ret
= ctdb_ltdb_fetch(ctdb_db
, key
, &header
, ctdb_db
, &data
);
3942 if (data
.dsize
== 0) {
3947 if (data
.dsize
!= sizeof(*seqnum
)) {
3948 DEBUG(DEBUG_ERR
, (__location__
" Invalid data received len=%zi\n",
3950 talloc_free(data
.dptr
);
3954 *seqnum
= *(uint64_t *)data
.dptr
;
3955 talloc_free(data
.dptr
);
3961 static int ctdb_store_db_seqnum(struct ctdb_transaction_handle
*h
,
3964 const char *keyname
= CTDB_DB_SEQNUM_KEY
;
3967 key
.dptr
= (uint8_t *)discard_const(keyname
);
3968 key
.dsize
= strlen(keyname
) + 1;
3970 data
.dptr
= (uint8_t *)&seqnum
;
3971 data
.dsize
= sizeof(seqnum
);
3973 return ctdb_transaction_store(h
, key
, data
);
3978 * commit a transaction
3980 int ctdb_transaction_commit(struct ctdb_transaction_handle
*h
)
3983 uint64_t old_seqnum
, new_seqnum
;
3985 struct timeval timeout
;
3987 if (h
->m_write
== NULL
) {
3988 /* no changes were made */
3993 ret
= ctdb_fetch_db_seqnum(h
->ctdb_db
, &old_seqnum
);
3995 DEBUG(DEBUG_ERR
, (__location__
" failed to fetch db sequence number\n"));
4000 new_seqnum
= old_seqnum
+ 1;
4001 ret
= ctdb_store_db_seqnum(h
, new_seqnum
);
4003 DEBUG(DEBUG_ERR
, (__location__
" failed to store db sequence number\n"));
4009 timeout
= timeval_current_ofs(30,0);
4010 ret
= ctdb_control(h
->ctdb_db
->ctdb
, CTDB_CURRENT_NODE
,
4012 CTDB_CONTROL_TRANS3_COMMIT
, 0,
4013 ctdb_marshall_finish(h
->m_write
), NULL
, NULL
,
4014 &status
, &timeout
, NULL
);
4015 if (ret
!= 0 || status
!= 0) {
4017 * TRANS3_COMMIT control will only fail if recovery has been
4018 * triggered. Check if the database has been updated or not.
4020 ret
= ctdb_fetch_db_seqnum(h
->ctdb_db
, &new_seqnum
);
4022 DEBUG(DEBUG_ERR
, (__location__
" failed to fetch db sequence number\n"));
4026 if (new_seqnum
== old_seqnum
) {
4027 /* Database not yet updated, try again */
4031 if (new_seqnum
!= (old_seqnum
+ 1)) {
4032 DEBUG(DEBUG_ERR
, (__location__
" new seqnum [%llu] != old seqnum [%llu] + 1\n",
4033 (long long unsigned)new_seqnum
,
4034 (long long unsigned)old_seqnum
));
4048 * cancel a transaction
4050 int ctdb_transaction_cancel(struct ctdb_transaction_handle
*h
)
4058 recovery daemon ping to main daemon
4060 int ctdb_ctrl_recd_ping(struct ctdb_context
*ctdb
)
4065 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0, CTDB_CONTROL_RECD_PING
, 0, tdb_null
,
4066 ctdb
, NULL
, &res
, NULL
, NULL
);
4067 if (ret
!= 0 || res
!= 0) {
4068 DEBUG(DEBUG_ERR
,("Failed to send recd ping\n"));
4076 tell the main daemon how long it took to lock the reclock file
4078 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context
*ctdb
, struct timeval timeout
, double latency
)
4084 data
.dptr
= (uint8_t *)&latency
;
4085 data
.dsize
= sizeof(latency
);
4087 ret
= ctdb_control(ctdb
, CTDB_CURRENT_NODE
, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY
, 0, data
,
4088 ctdb
, NULL
, &res
, NULL
, NULL
);
4089 if (ret
!= 0 || res
!= 0) {
4090 DEBUG(DEBUG_ERR
,("Failed to send recd reclock latency\n"));
4098 get the name of the reclock file
4100 int ctdb_ctrl_getreclock(struct ctdb_context
*ctdb
, struct timeval timeout
,
4101 uint32_t destnode
, TALLOC_CTX
*mem_ctx
,
4108 ret
= ctdb_control(ctdb
, destnode
, 0,
4109 CTDB_CONTROL_GET_RECLOCK_FILE
, 0, tdb_null
,
4110 mem_ctx
, &data
, &res
, &timeout
, NULL
);
4111 if (ret
!= 0 || res
!= 0) {
4115 if (data
.dsize
== 0) {
4118 *name
= talloc_strdup(mem_ctx
, discard_const(data
.dptr
));
4120 talloc_free(data
.dptr
);
4128 int ctdb_ctrl_stop_node(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
)
4133 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_STOP_NODE
, 0, tdb_null
,
4134 ctdb
, NULL
, &res
, &timeout
, NULL
);
4135 if (ret
!= 0 || res
!= 0) {
4136 DEBUG(DEBUG_ERR
,("Failed to stop node\n"));
4146 int ctdb_ctrl_continue_node(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
)
4150 ret
= ctdb_control(ctdb
, destnode
, 0, CTDB_CONTROL_CONTINUE_NODE
, 0, tdb_null
,
4151 ctdb
, NULL
, NULL
, &timeout
, NULL
);
4153 DEBUG(DEBUG_ERR
,("Failed to continue node\n"));
4161 set the lmaster role for a node
4163 int ctdb_ctrl_setlmasterrole(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t lmasterrole
)
4169 data
.dsize
= sizeof(lmasterrole
);
4170 data
.dptr
= (uint8_t *)&lmasterrole
;
4172 ret
= ctdb_control(ctdb
, destnode
, 0,
4173 CTDB_CONTROL_SET_LMASTERROLE
, 0, data
,
4174 NULL
, NULL
, &res
, &timeout
, NULL
);
4175 if (ret
!= 0 || res
!= 0) {
4176 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setlmasterrole failed\n"));
4184 set the recmaster role for a node
4186 int ctdb_ctrl_setrecmasterrole(struct ctdb_context
*ctdb
, struct timeval timeout
, uint32_t destnode
, uint32_t recmasterrole
)
4192 data
.dsize
= sizeof(recmasterrole
);
4193 data
.dptr
= (uint8_t *)&recmasterrole
;
4195 ret
= ctdb_control(ctdb
, destnode
, 0,
4196 CTDB_CONTROL_SET_RECMASTERROLE
, 0, data
,
4197 NULL
, NULL
, &res
, &timeout
, NULL
);
4198 if (ret
!= 0 || res
!= 0) {
4199 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for setrecmasterrole failed\n"));
4206 int ctdb_ctrl_set_ban(struct ctdb_context
*ctdb
, struct timeval timeout
,
4207 uint32_t destnode
, struct ctdb_ban_state
*bantime
)
4213 data
.dsize
= sizeof(*bantime
);
4214 data
.dptr
= (uint8_t *)bantime
;
4216 ret
= ctdb_control(ctdb
, destnode
, 0,
4217 CTDB_CONTROL_SET_BAN_STATE
, 0, data
,
4218 NULL
, NULL
, &res
, &timeout
, NULL
);
4219 if (ret
!= 0 || res
!= 0) {
4220 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for set ban state failed\n"));
4228 int ctdb_ctrl_get_ban(struct ctdb_context
*ctdb
, struct timeval timeout
,
4229 uint32_t destnode
, TALLOC_CTX
*mem_ctx
,
4230 struct ctdb_ban_state
**bantime
)
4235 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
4237 ret
= ctdb_control(ctdb
, destnode
, 0,
4238 CTDB_CONTROL_GET_BAN_STATE
, 0, tdb_null
,
4239 tmp_ctx
, &outdata
, &res
, &timeout
, NULL
);
4240 if (ret
!= 0 || res
!= 0) {
4241 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for set ban state failed\n"));
4242 talloc_free(tmp_ctx
);
4246 *bantime
= (struct ctdb_ban_state
*)talloc_steal(mem_ctx
, outdata
.dptr
);
4247 talloc_free(tmp_ctx
);
4252 int ctdb_ctrl_getstathistory(struct ctdb_context
*ctdb
,
4253 struct timeval timeout
, uint32_t destnode
,
4254 TALLOC_CTX
*mem_ctx
,
4255 struct ctdb_statistics_list_old
**stats
)
4261 ret
= ctdb_control(ctdb
, destnode
, 0,
4262 CTDB_CONTROL_GET_STAT_HISTORY
, 0, tdb_null
,
4263 mem_ctx
, &outdata
, &res
, &timeout
, NULL
);
4264 if (ret
!= 0 || res
!= 0 || outdata
.dsize
== 0) {
4265 DEBUG(DEBUG_ERR
,(__location__
" ctdb_control for getstathistory failed ret:%d res:%d\n", ret
, res
));
4269 *stats
= (struct ctdb_statistics_list_old
*)talloc_memdup(mem_ctx
,
4272 talloc_free(outdata
.dptr
);
4277 struct ctdb_ltdb_header
*ctdb_header_from_record_handle(struct ctdb_record_handle
*h
)
4287 struct ctdb_client_control_state
*
4288 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
)
4290 struct ctdb_client_control_state
*handle
;
4291 struct ctdb_marshall_buffer
*m
;
4292 struct ctdb_rec_data_old
*rec
;
4295 m
= talloc_zero(mem_ctx
, struct ctdb_marshall_buffer
);
4297 DEBUG(DEBUG_ERR
, ("Failed to allocate marshall buffer for update record\n"));
4301 m
->db_id
= ctdb_db
->db_id
;
4303 rec
= ctdb_marshall_record(m
, 0, key
, header
, data
);
4305 DEBUG(DEBUG_ERR
,("Failed to marshall record for update record\n"));
4309 m
= talloc_realloc_size(mem_ctx
, m
, rec
->length
+ offsetof(struct ctdb_marshall_buffer
, data
));
4311 DEBUG(DEBUG_CRIT
,(__location__
" Failed to expand recdata\n"));
4316 memcpy((uint8_t *)m
+ offsetof(struct ctdb_marshall_buffer
, data
), rec
, rec
->length
);
4319 outdata
.dptr
= (uint8_t *)m
;
4320 outdata
.dsize
= talloc_get_size(m
);
4322 handle
= ctdb_control_send(ctdb
, destnode
, 0,
4323 CTDB_CONTROL_UPDATE_RECORD
, 0, outdata
,
4324 mem_ctx
, &timeout
, NULL
);
4329 int ctdb_ctrl_updaterecord_recv(struct ctdb_context
*ctdb
, struct ctdb_client_control_state
*state
)
4334 ret
= ctdb_control_recv(ctdb
, state
, state
, NULL
, &res
, NULL
);
4335 if ( (ret
!= 0) || (res
!= 0) ){
4336 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_update_record_recv failed\n"));
4344 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
)
4346 struct ctdb_client_control_state
*state
;
4348 state
= ctdb_ctrl_updaterecord_send(ctdb
, mem_ctx
, timeout
, destnode
, ctdb_db
, key
, header
, data
);
4349 return ctdb_ctrl_updaterecord_recv(ctdb
, state
);
4358 set a database to be readonly
4360 struct ctdb_client_control_state
*
4361 ctdb_ctrl_set_db_readonly_send(struct ctdb_context
*ctdb
, uint32_t destnode
, uint32_t dbid
)
4365 data
.dptr
= (uint8_t *)&dbid
;
4366 data
.dsize
= sizeof(dbid
);
4368 return ctdb_control_send(ctdb
, destnode
, 0,
4369 CTDB_CONTROL_SET_DB_READONLY
, 0, data
,
4373 int ctdb_ctrl_set_db_readonly_recv(struct ctdb_context
*ctdb
, struct ctdb_client_control_state
*state
)
4378 ret
= ctdb_control_recv(ctdb
, state
, ctdb
, NULL
, &res
, NULL
);
4379 if (ret
!= 0 || res
!= 0) {
4380 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_set_db_readonly_recv failed ret:%d res:%d\n", ret
, res
));
4387 int ctdb_ctrl_set_db_readonly(struct ctdb_context
*ctdb
, uint32_t destnode
, uint32_t dbid
)
4389 struct ctdb_client_control_state
*state
;
4391 state
= ctdb_ctrl_set_db_readonly_send(ctdb
, destnode
, dbid
);
4392 return ctdb_ctrl_set_db_readonly_recv(ctdb
, state
);
4396 set a database to be sticky
4398 struct ctdb_client_control_state
*
4399 ctdb_ctrl_set_db_sticky_send(struct ctdb_context
*ctdb
, uint32_t destnode
, uint32_t dbid
)
4403 data
.dptr
= (uint8_t *)&dbid
;
4404 data
.dsize
= sizeof(dbid
);
4406 return ctdb_control_send(ctdb
, destnode
, 0,
4407 CTDB_CONTROL_SET_DB_STICKY
, 0, data
,
4411 int ctdb_ctrl_set_db_sticky_recv(struct ctdb_context
*ctdb
, struct ctdb_client_control_state
*state
)
4416 ret
= ctdb_control_recv(ctdb
, state
, ctdb
, NULL
, &res
, NULL
);
4417 if (ret
!= 0 || res
!= 0) {
4418 DEBUG(DEBUG_ERR
,(__location__
" ctdb_ctrl_set_db_sticky_recv failed ret:%d res:%d\n", ret
, res
));
4425 int ctdb_ctrl_set_db_sticky(struct ctdb_context
*ctdb
, uint32_t destnode
, uint32_t dbid
)
4427 struct ctdb_client_control_state
*state
;
4429 state
= ctdb_ctrl_set_db_sticky_send(ctdb
, destnode
, dbid
);
4430 return ctdb_ctrl_set_db_sticky_recv(ctdb
, state
);